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,299 @@
|
|
1
|
+
# This file holds the key press and modifier events.
|
2
|
+
|
3
|
+
require 'sdl'
|
4
|
+
|
5
|
+
#
|
6
|
+
module Tea
|
7
|
+
|
8
|
+
module Kbd
|
9
|
+
# Event generated when a key is pressed down.
|
10
|
+
#
|
11
|
+
# +key+:: Physical key that was pressed, as a symbol (see key reference).
|
12
|
+
# +mods+:: Hash of the active key modifiers. Values are +true+ or
|
13
|
+
# +false+, and the keys can be: +:L_SHIFT+, +:R_SHIFT+,
|
14
|
+
# +:L_CTRL+, +:R_CTRL+, +:L_ALT+, +:R_ALT+, +:NUM_LOCK+,
|
15
|
+
# +:CAPS_LOCK+, +:ALT_GR+. Also, +:SHIFT+, +:CTRL+ and +:ALT+
|
16
|
+
# are provided for convenience, and Tea key constants with the
|
17
|
+
# same names can be used instead.
|
18
|
+
# +char+:: String character generated by that key and those modifiers.
|
19
|
+
# With Ruby >= 1.9, the encoding of this character is UTF-8,
|
20
|
+
# otherwise it varies with the running environment.
|
21
|
+
class Down
|
22
|
+
attr_reader :key, :mods, :char
|
23
|
+
def initialize(sdl_event)
|
24
|
+
@key = Kbd.instance_variable_get(:@sdl_key_table)[sdl_event.sym]
|
25
|
+
@mods = Kbd.send(:decode_modifiers, sdl_event.mod)
|
26
|
+
|
27
|
+
# Ruby 1.9 uses UTF-8 Unicode encoding. Below this, who knows how
|
28
|
+
# Unicode code points are interpreted?
|
29
|
+
if sdl_event.unicode != 0
|
30
|
+
unicode_field = "%c"
|
31
|
+
ruby_minor = RUBY_VERSION.match(/\.(\d+)\./)
|
32
|
+
if ruby_minor && ruby_minor[1].to_i >= 9
|
33
|
+
unicode_field = unicode_field.encode('utf-8')
|
34
|
+
end
|
35
|
+
@char = unicode_field % sdl_event.unicode
|
36
|
+
else
|
37
|
+
@char = ''
|
38
|
+
end
|
39
|
+
end
|
40
|
+
end
|
41
|
+
|
42
|
+
# Event generated when a held-down key is released. +key+ and +mods+ are
|
43
|
+
# the same as in KeyDown.
|
44
|
+
#
|
45
|
+
# +key+:: Physical key that was pressed, as a symbol (see key reference).
|
46
|
+
# +mods+:: Hash of the active key modifiers. Values are +true+ or
|
47
|
+
# +false+, and the keys can be: +:L_SHIFT+, +:R_SHIFT+,
|
48
|
+
# +:L_CTRL+, +:R_CTRL+, +:L_ALT+, +:R_ALT+, +:NUM_LOCK+,
|
49
|
+
# +:CAPS_LOCK+, +:ALT_GR+. Also, +:SHIFT+, +:CTRL+ and +:ALT+
|
50
|
+
# are provided for convenience, and Tea key constants with the
|
51
|
+
# same names can be used instead.
|
52
|
+
class Up
|
53
|
+
attr_reader :key, :mods
|
54
|
+
def initialize(sdl_event)
|
55
|
+
@key = Kbd.instance_variable_get(:@sdl_key_table)[sdl_event.sym]
|
56
|
+
@mods = Kbd.send(:decode_modifiers, sdl_event.mod)
|
57
|
+
end
|
58
|
+
end
|
59
|
+
|
60
|
+
# Returns +true+ if +key+ is being pressed down.
|
61
|
+
def Kbd.key_down?(key)
|
62
|
+
if (down = @key_states[key]) == nil
|
63
|
+
raise Tea::Error, "Can't find key #{key} to check", caller
|
64
|
+
end
|
65
|
+
down
|
66
|
+
end
|
67
|
+
|
68
|
+
# Returns true if the modifier is 'active'. For +:L_SHIFT+, +:R_SHIFT+,
|
69
|
+
# +:L_CTRL+, +:R_CTRL+, +:L_ALT+, and +:ALT_GR+ (and convenience modifier
|
70
|
+
# constants +:SHIFT+, +:CTRL+ and +:ALT+), this means they're being held
|
71
|
+
# down. For +:NUM_LOCK+ and +:CAPS_LOCK+, this means their toggle is on.
|
72
|
+
def Kbd.mod_active?(mod)
|
73
|
+
if (active = @mod_states[mod]) == nil
|
74
|
+
raise Tea::Error, "Can't find modifier #{mod} to check", caller
|
75
|
+
end
|
76
|
+
active
|
77
|
+
end
|
78
|
+
|
79
|
+
# Returns true if the keyboard is focused in the screen window.
|
80
|
+
def Kbd.in_app?
|
81
|
+
@in_app = true if !instance_variable_defined?(:@in_app)
|
82
|
+
@in_app
|
83
|
+
end
|
84
|
+
|
85
|
+
# Update the keyboard state, so that Kbd.key_down? and Kbd.mod_active?
|
86
|
+
# provide fresh data. Called automatically by Event.get.
|
87
|
+
def Kbd.update_state(tea_event)
|
88
|
+
case tea_event
|
89
|
+
when Down, Up
|
90
|
+
@key_states[tea_event.key] = (tea_event.class == Down)
|
91
|
+
@mod_states.merge! tea_event.mods
|
92
|
+
when Lost then @in_app = false
|
93
|
+
when Gained then @in_app = true
|
94
|
+
end
|
95
|
+
end
|
96
|
+
|
97
|
+
# Decode the SDL key event mod into a hash of easily consulted key modifier
|
98
|
+
# symbols. For internal use only.
|
99
|
+
def Kbd.decode_modifiers(sdl_key_event_mod)
|
100
|
+
mods = {}
|
101
|
+
|
102
|
+
mods[:L_SHIFT] = (sdl_key_event_mod & SDL::Key::MOD_LSHIFT) != 0
|
103
|
+
mods[:R_SHIFT] = (sdl_key_event_mod & SDL::Key::MOD_RSHIFT) != 0
|
104
|
+
mods[:SHIFT] = mods[:L_SHIFT] || mods[:R_SHIFT]
|
105
|
+
|
106
|
+
mods[:L_CTRL] = (sdl_key_event_mod & SDL::Key::MOD_LCTRL) != 0
|
107
|
+
mods[:R_CTRL] = (sdl_key_event_mod & SDL::Key::MOD_RCTRL) != 0
|
108
|
+
mods[:CTRL] = mods[:L_CTRL] || mods[:R_CTRL]
|
109
|
+
|
110
|
+
mods[:L_ALT] = (sdl_key_event_mod & SDL::Key::MOD_LALT) != 0
|
111
|
+
mods[:R_ALT] = (sdl_key_event_mod & SDL::Key::MOD_RALT) != 0
|
112
|
+
mods[:ALT] = mods[:L_ALT] || mods[:R_ALT]
|
113
|
+
|
114
|
+
mods[:NUM_LOCK] = (sdl_key_event_mod & SDL::Key::MOD_NUM) != 0
|
115
|
+
mods[:CAPS_LOCK] = (sdl_key_event_mod & SDL::Key::MOD_CAPS) != 0
|
116
|
+
mods[:ALT_GR] = (sdl_key_event_mod & SDL::Key::MOD_MODE) != 0
|
117
|
+
|
118
|
+
mods
|
119
|
+
end
|
120
|
+
private_class_method :decode_modifiers
|
121
|
+
|
122
|
+
# Big fat table of SDL keys to Ruby strings. For internal use only.
|
123
|
+
@sdl_key_table = { SDL::Key::BACKSPACE => :BACKSPACE,
|
124
|
+
SDL::Key::TAB => :TAB,
|
125
|
+
#SDL::Key::CLEAR => clear, # ???
|
126
|
+
SDL::Key::RETURN => :ENTER,
|
127
|
+
SDL::Key::PAUSE => :PAUSE,
|
128
|
+
SDL::Key::ESCAPE => :ESCAPE,
|
129
|
+
SDL::Key::SPACE => :SPACE,
|
130
|
+
SDL::Key::EXCLAIM => :EXCLAMATION_MARK,
|
131
|
+
SDL::Key::QUOTEDBL => :DOUBLE_QUOTE,
|
132
|
+
SDL::Key::HASH => :HASH,
|
133
|
+
SDL::Key::DOLLAR => :DOLLAR,
|
134
|
+
SDL::Key::AMPERSAND => :AMPERSAND,
|
135
|
+
SDL::Key::QUOTE => :QUOTE,
|
136
|
+
SDL::Key::LEFTPAREN => :OPEN_PAREN,
|
137
|
+
SDL::Key::RIGHTPAREN => :CLOSE_PAREN,
|
138
|
+
SDL::Key::ASTERISK => :ASTERISK,
|
139
|
+
SDL::Key::PLUS => :PLUS,
|
140
|
+
SDL::Key::COMMA => :COMMA,
|
141
|
+
SDL::Key::MINUS => :MINUS,
|
142
|
+
SDL::Key::PERIOD => :PERIOD,
|
143
|
+
SDL::Key::SLASH => :SLASH,
|
144
|
+
SDL::Key::K0 => :K0,
|
145
|
+
SDL::Key::K1 => :K1,
|
146
|
+
SDL::Key::K2 => :K2,
|
147
|
+
SDL::Key::K3 => :K3,
|
148
|
+
SDL::Key::K4 => :K4,
|
149
|
+
SDL::Key::K5 => :K5,
|
150
|
+
SDL::Key::K6 => :K6,
|
151
|
+
SDL::Key::K7 => :K7,
|
152
|
+
SDL::Key::K8 => :K8,
|
153
|
+
SDL::Key::K9 => :K9,
|
154
|
+
SDL::Key::COLON => :COLON,
|
155
|
+
SDL::Key::SEMICOLON => :SEMICOLON,
|
156
|
+
SDL::Key::LESS => :LESS_THAN,
|
157
|
+
SDL::Key::EQUALS => :EQUALS,
|
158
|
+
SDL::Key::GREATER => :GREATER_THAN,
|
159
|
+
SDL::Key::QUESTION => :QUESTION_MARK,
|
160
|
+
SDL::Key::AT => :AT,
|
161
|
+
SDL::Key::LEFTBRACKET => :OPEN_SQUARE_BRACKET,
|
162
|
+
SDL::Key::BACKSLASH => :BACKSLASH,
|
163
|
+
SDL::Key::RIGHTBRACKET => :CLOSE_SQUARE_BRACKET,
|
164
|
+
SDL::Key::CARET => :CARET,
|
165
|
+
SDL::Key::UNDERSCORE => :UNDERSCORE,
|
166
|
+
SDL::Key::BACKQUOTE => :BACKTICK,
|
167
|
+
SDL::Key::A => :A,
|
168
|
+
SDL::Key::B => :B,
|
169
|
+
SDL::Key::C => :C,
|
170
|
+
SDL::Key::D => :D,
|
171
|
+
SDL::Key::E => :E,
|
172
|
+
SDL::Key::F => :F,
|
173
|
+
SDL::Key::G => :G,
|
174
|
+
SDL::Key::H => :H,
|
175
|
+
SDL::Key::I => :I,
|
176
|
+
SDL::Key::J => :J,
|
177
|
+
SDL::Key::K => :K,
|
178
|
+
SDL::Key::L => :L,
|
179
|
+
SDL::Key::M => :M,
|
180
|
+
SDL::Key::N => :N,
|
181
|
+
SDL::Key::O => :O,
|
182
|
+
SDL::Key::P => :P,
|
183
|
+
SDL::Key::Q => :Q,
|
184
|
+
SDL::Key::R => :R,
|
185
|
+
SDL::Key::S => :S,
|
186
|
+
SDL::Key::T => :T,
|
187
|
+
SDL::Key::U => :U,
|
188
|
+
SDL::Key::V => :V,
|
189
|
+
SDL::Key::W => :W,
|
190
|
+
SDL::Key::X => :X,
|
191
|
+
SDL::Key::Y => :Y,
|
192
|
+
SDL::Key::Z => :Z,
|
193
|
+
SDL::Key::DELETE => :DELETE,
|
194
|
+
SDL::Key::KP0 => :NP0,
|
195
|
+
SDL::Key::KP1 => :NP1,
|
196
|
+
SDL::Key::KP2 => :NP2,
|
197
|
+
SDL::Key::KP3 => :NP3,
|
198
|
+
SDL::Key::KP4 => :NP4,
|
199
|
+
SDL::Key::KP5 => :NP5,
|
200
|
+
SDL::Key::KP6 => :NP6,
|
201
|
+
SDL::Key::KP7 => :NP7,
|
202
|
+
SDL::Key::KP8 => :NP8,
|
203
|
+
SDL::Key::KP9 => :NP9,
|
204
|
+
SDL::Key::KP_PERIOD => :NP_PERIOD,
|
205
|
+
SDL::Key::KP_DIVIDE => :NP_DIVIDE,
|
206
|
+
SDL::Key::KP_MULTIPLY => :NP_MULTIPLY,
|
207
|
+
SDL::Key::KP_MINUS => :NP_MINUS,
|
208
|
+
SDL::Key::KP_PLUS => :NP_PLUS,
|
209
|
+
SDL::Key::KP_ENTER => :NP_ENTER,
|
210
|
+
SDL::Key::KP_EQUALS => :NP_EQUALS,
|
211
|
+
SDL::Key::UP => :UP,
|
212
|
+
SDL::Key::DOWN => :DOWN,
|
213
|
+
SDL::Key::RIGHT => :RIGHT,
|
214
|
+
SDL::Key::LEFT => :LEFT,
|
215
|
+
SDL::Key::INSERT => :INSERT,
|
216
|
+
SDL::Key::HOME => :HOME,
|
217
|
+
SDL::Key::END => :END,
|
218
|
+
SDL::Key::PAGEUP => :PAGE_UP,
|
219
|
+
SDL::Key::PAGEDOWN => :PAGE_DOWN,
|
220
|
+
SDL::Key::F1 => :F1,
|
221
|
+
SDL::Key::F2 => :F2,
|
222
|
+
SDL::Key::F3 => :F3,
|
223
|
+
SDL::Key::F4 => :F4,
|
224
|
+
SDL::Key::F5 => :F5,
|
225
|
+
SDL::Key::F6 => :F6,
|
226
|
+
SDL::Key::F7 => :F7,
|
227
|
+
SDL::Key::F8 => :F8,
|
228
|
+
SDL::Key::F9 => :F9,
|
229
|
+
SDL::Key::F10 => :F10,
|
230
|
+
SDL::Key::F11 => :F11,
|
231
|
+
SDL::Key::F12 => :F12,
|
232
|
+
#SDL::Key::F13 => F13, # Who
|
233
|
+
#SDL::Key::F14 => F14, # has
|
234
|
+
#SDL::Key::F15 => F15, # these?
|
235
|
+
SDL::Key::NUMLOCK => :NUM_LOCK,
|
236
|
+
SDL::Key::CAPSLOCK => :CAPS_LOCK,
|
237
|
+
SDL::Key::SCROLLOCK => :SCROLL_LOCK,
|
238
|
+
SDL::Key::RSHIFT => :R_SHIFT,
|
239
|
+
SDL::Key::LSHIFT => :L_SHIFT,
|
240
|
+
SDL::Key::RCTRL => :R_CTRL,
|
241
|
+
SDL::Key::LCTRL => :L_CTRL,
|
242
|
+
SDL::Key::RALT => :R_ALT,
|
243
|
+
SDL::Key::LALT => :L_ALT,
|
244
|
+
#SDL::Key::RMETA => right meta, # 'meta' should
|
245
|
+
#SDL::Key::LMETA => left meta, # be 'alt'?
|
246
|
+
SDL::Key::LSUPER => :L_SUPER,
|
247
|
+
SDL::Key::RSUPER => :R_SUPER,
|
248
|
+
SDL::Key::MODE => :ALT_GR,
|
249
|
+
#SDL::Key::HELP => help, # Rare enough to cause problems.
|
250
|
+
SDL::Key::PRINT => :PRINT_SCREEN,
|
251
|
+
SDL::Key::SYSREQ => :SYS_REQ,
|
252
|
+
SDL::Key::BREAK => :BREAK,
|
253
|
+
SDL::Key::MENU => :MENU,
|
254
|
+
#SDL::Key::POWER => power, # "Power Macintosh" power key
|
255
|
+
SDL::Key::EURO => :EURO, # Some European keyboards need this.
|
256
|
+
}
|
257
|
+
|
258
|
+
# Define Tea key symbols as constants to avoid typo errors.
|
259
|
+
@sdl_key_table.each_value { |sym| const_set(sym, sym) }
|
260
|
+
|
261
|
+
# Extra modifier constants for making modifier detection more consistent.
|
262
|
+
SHIFT = :shift
|
263
|
+
CTRL = :ctrl
|
264
|
+
ALT = :alt
|
265
|
+
|
266
|
+
# Initialise key states to false, as opposed to nil.
|
267
|
+
@key_states = {}
|
268
|
+
@sdl_key_table.each_value { |sym| @key_states[sym] = false }
|
269
|
+
|
270
|
+
# Modifier states, same deal.
|
271
|
+
@mod_states = { :L_SHIFT => false, :R_SHIFT => false, :SHIFT => false,
|
272
|
+
:L_CTRL => false, :R_CTRL => false, :CTRL => false,
|
273
|
+
:L_ALT => false, :R_ALT => false, :ALT => false,
|
274
|
+
:NUM_LOCK => false,
|
275
|
+
:CAPS_LOCK => false,
|
276
|
+
:ALT_GR => false }
|
277
|
+
end
|
278
|
+
|
279
|
+
module Event
|
280
|
+
|
281
|
+
# Convert a keyboard-related SDL::Event into a Tea event. For internal use
|
282
|
+
# only.
|
283
|
+
def Event.translate_keyboard_event(sdl_event)
|
284
|
+
out_events = []
|
285
|
+
|
286
|
+
case sdl_event
|
287
|
+
when SDL::Event::KeyDown
|
288
|
+
out_events.push Kbd::Down.new(sdl_event)
|
289
|
+
when SDL::Event::KeyUp
|
290
|
+
out_events.push Kbd::Up.new(sdl_event)
|
291
|
+
end
|
292
|
+
|
293
|
+
out_events
|
294
|
+
end
|
295
|
+
private_class_method :translate_keyboard_event
|
296
|
+
|
297
|
+
end
|
298
|
+
|
299
|
+
end
|
@@ -0,0 +1,190 @@
|
|
1
|
+
# This file holds the mouse motion and button events.
|
2
|
+
|
3
|
+
require 'sdl'
|
4
|
+
|
5
|
+
# Hot-patch for Ruby/SDL for missing mouse wheel constants.
|
6
|
+
module SDL
|
7
|
+
module Mouse
|
8
|
+
BUTTON_WHEELUP = 4
|
9
|
+
BUTTON_WHEELDOWN = 5
|
10
|
+
end
|
11
|
+
end
|
12
|
+
|
13
|
+
#
|
14
|
+
module Tea
|
15
|
+
|
16
|
+
module Mouse
|
17
|
+
|
18
|
+
# Mouse button constants for mouse events.
|
19
|
+
LEFT = :LEFT
|
20
|
+
MIDDLE = :MIDDLE
|
21
|
+
RIGHT = :RIGHT
|
22
|
+
|
23
|
+
# Event generated when the mouse cursor is moved.
|
24
|
+
#
|
25
|
+
# +x+, +y+:: coordinates of the mouse cursor
|
26
|
+
# +buttons+:: an array that may contain +:left+, +:middle+ and +:right+
|
27
|
+
class Move
|
28
|
+
attr_reader :x, :y, :buttons
|
29
|
+
def initialize(sdl_event)
|
30
|
+
@x = sdl_event.x
|
31
|
+
@y = sdl_event.y
|
32
|
+
@buttons = {}
|
33
|
+
@buttons[Mouse::LEFT] = (sdl_event.state & SDL::Mouse::BUTTON_LMASK) != 0
|
34
|
+
@buttons[Mouse::MIDDLE] = (sdl_event.state & SDL::Mouse::BUTTON_MMASK) != 0
|
35
|
+
@buttons[Mouse::RIGHT] = (sdl_event.state & SDL::Mouse::BUTTON_RMASK) != 0
|
36
|
+
end
|
37
|
+
end
|
38
|
+
|
39
|
+
# Event generated when a mouse button is held down.
|
40
|
+
#
|
41
|
+
# +x+, +y+:: coordinates of the mouse cursor
|
42
|
+
# +button+:: the mouse button that is down: +:left+, +:middle+ or +:right+
|
43
|
+
class Down
|
44
|
+
attr_reader :x, :y, :button
|
45
|
+
def initialize(sdl_event)
|
46
|
+
@x = sdl_event.x
|
47
|
+
@y = sdl_event.y
|
48
|
+
case sdl_event.button
|
49
|
+
when SDL::Mouse::BUTTON_LEFT then @button = Mouse::LEFT
|
50
|
+
when SDL::Mouse::BUTTON_MIDDLE then @button = Mouse::MIDDLE
|
51
|
+
when SDL::Mouse::BUTTON_RIGHT then @button = Mouse::RIGHT
|
52
|
+
end
|
53
|
+
end
|
54
|
+
end
|
55
|
+
|
56
|
+
# Event generated when a mouse button that was held down is released.
|
57
|
+
#
|
58
|
+
# +x+, +y+:: coordinates of the mouse cursor
|
59
|
+
# +button+:: the mouse button that was released: +:left+, +:middle+ or
|
60
|
+
# +:right+
|
61
|
+
class Up
|
62
|
+
attr_reader :x, :y, :button
|
63
|
+
def initialize(sdl_event)
|
64
|
+
@x = sdl_event.x
|
65
|
+
@y = sdl_event.y
|
66
|
+
case sdl_event.button
|
67
|
+
when SDL::Mouse::BUTTON_LEFT then @button = Mouse::LEFT
|
68
|
+
when SDL::Mouse::BUTTON_MIDDLE then @button = Mouse::MIDDLE
|
69
|
+
when SDL::Mouse::BUTTON_RIGHT then @button = Mouse::RIGHT
|
70
|
+
end
|
71
|
+
end
|
72
|
+
end
|
73
|
+
|
74
|
+
# Event generated when the mouse wheel is scrolled.
|
75
|
+
#
|
76
|
+
# +x+, +y+:: coordinates of the mouse cursor.
|
77
|
+
# +delta+:: 1 when scrolling down, -1 when scrolling up.
|
78
|
+
class Scroll
|
79
|
+
attr_reader :x, :y, :delta
|
80
|
+
def initialize(sdl_event)
|
81
|
+
@x = sdl_event.x
|
82
|
+
@y = sdl_event.y
|
83
|
+
case sdl_event.button
|
84
|
+
when SDL::Mouse::BUTTON_WHEELDOWN then @delta = 1
|
85
|
+
when SDL::Mouse::BUTTON_WHEELUP then @delta = -1
|
86
|
+
else
|
87
|
+
raise Tea::Error, "Tea::Mouse::Scroll given an unexpected event: #{sdl_event.inspect}", caller
|
88
|
+
end
|
89
|
+
end
|
90
|
+
end
|
91
|
+
|
92
|
+
# Report the x position of the mouse in the screen window. Updated when
|
93
|
+
# Event.get is called.
|
94
|
+
def Mouse.x
|
95
|
+
@x = 0 if !instance_variable_defined?(:@x)
|
96
|
+
@x
|
97
|
+
end
|
98
|
+
|
99
|
+
# Report the y position of the mouse in the screen window. Updated when
|
100
|
+
# Event.get is called.
|
101
|
+
def Mouse.y
|
102
|
+
@y = 0 if !instance_variable_defined?(:@y)
|
103
|
+
@y
|
104
|
+
end
|
105
|
+
|
106
|
+
# Returns true if the left mouse button is down. Updated when Event.get is
|
107
|
+
# called.
|
108
|
+
def Mouse.left?
|
109
|
+
@left = false if !instance_variable_defined?(:@left)
|
110
|
+
@left
|
111
|
+
end
|
112
|
+
|
113
|
+
# Returns true if the middle mouse button is down. Updated when Event.get
|
114
|
+
# is called.
|
115
|
+
def Mouse.middle?
|
116
|
+
@middle = false if !instance_variable_defined?(:@middle)
|
117
|
+
@middle
|
118
|
+
end
|
119
|
+
|
120
|
+
# Returns true if the right mouse button is down. Updated when Event.get
|
121
|
+
# is called.
|
122
|
+
def Mouse.right?
|
123
|
+
@right = false if !instance_variable_defined?(:@right)
|
124
|
+
@right
|
125
|
+
end
|
126
|
+
|
127
|
+
# Returns true if the mouse is in the screen window
|
128
|
+
def Mouse.in_app?
|
129
|
+
@in_app = true if !instance_variable_defined?(:@in_app)
|
130
|
+
@in_app
|
131
|
+
end
|
132
|
+
|
133
|
+
# Update the mouse state, so that Mouse.x, Mouse.y, Mouse.left?,
|
134
|
+
# Mouse.middle? and Mouse.right? return recent data.
|
135
|
+
def Mouse.update_state(tea_event)
|
136
|
+
case tea_event
|
137
|
+
when Move
|
138
|
+
@x = tea_event.x
|
139
|
+
@y = tea_event.y
|
140
|
+
when Down
|
141
|
+
case tea_event.button
|
142
|
+
when LEFT then @left = true
|
143
|
+
when MIDDLE then @middle = true
|
144
|
+
when RIGHT then @right = true
|
145
|
+
end
|
146
|
+
when Up
|
147
|
+
case tea_event.button
|
148
|
+
when LEFT then @left = false
|
149
|
+
when MIDDLE then @middle = false
|
150
|
+
when RIGHT then @right = false
|
151
|
+
end
|
152
|
+
when Lost
|
153
|
+
@in_app = false
|
154
|
+
when Gained
|
155
|
+
@in_app = true
|
156
|
+
end
|
157
|
+
end
|
158
|
+
end
|
159
|
+
|
160
|
+
module Event
|
161
|
+
|
162
|
+
# Convert a mouse-related SDL::Event into a Tea event. For internal use only.
|
163
|
+
def Event.translate_mouse_event(sdl_event)
|
164
|
+
out_events = []
|
165
|
+
|
166
|
+
case sdl_event
|
167
|
+
when SDL::Event::MouseMotion
|
168
|
+
out_events.push Mouse::Move.new(sdl_event)
|
169
|
+
when SDL::Event::MouseButtonDown
|
170
|
+
case sdl_event.button
|
171
|
+
when SDL::Mouse::BUTTON_LEFT, SDL::Mouse::BUTTON_MIDDLE, SDL::Mouse::BUTTON_RIGHT
|
172
|
+
out_events.push Mouse::Down.new(sdl_event)
|
173
|
+
when SDL::Mouse::BUTTON_WHEELDOWN, SDL::Mouse::BUTTON_WHEELUP
|
174
|
+
out_events.push Mouse::Scroll.new(sdl_event)
|
175
|
+
end
|
176
|
+
when SDL::Event::MouseButtonUp
|
177
|
+
# Ignore MouseButtonUp for the scroll wheel.
|
178
|
+
case sdl_event.button
|
179
|
+
when SDL::Mouse::BUTTON_LEFT, SDL::Mouse::BUTTON_MIDDLE, SDL::Mouse::BUTTON_RIGHT
|
180
|
+
out_events.push Mouse::Up.new(sdl_event)
|
181
|
+
end
|
182
|
+
end
|
183
|
+
|
184
|
+
out_events
|
185
|
+
end
|
186
|
+
private_class_method :translate_mouse_event
|
187
|
+
|
188
|
+
end
|
189
|
+
|
190
|
+
end
|
@@ -0,0 +1,79 @@
|
|
1
|
+
# This file holds the classes and methods needed to draw primitives on Bitmaps.
|
2
|
+
|
3
|
+
require 'sdl'
|
4
|
+
|
5
|
+
#
|
6
|
+
module Tea
|
7
|
+
|
8
|
+
private
|
9
|
+
|
10
|
+
# The PrimitiveDrawing mixin enables primitive shapes to be drawn to classes
|
11
|
+
# with an internal SDL::Surface.
|
12
|
+
#
|
13
|
+
# To use this mixin, include it and implement/alias a +primitive_buffer+
|
14
|
+
# method that gets the object's SDL::Surface.
|
15
|
+
#
|
16
|
+
# include 'PrimitiveDrawing'
|
17
|
+
# def primitive_buffer
|
18
|
+
# @internal_sdl_buffer
|
19
|
+
# end
|
20
|
+
module PrimitiveDrawing
|
21
|
+
|
22
|
+
# Clear the drawing buffer. This is the same as drawing a completely black
|
23
|
+
# rectangle over the whole buffer.
|
24
|
+
def clear
|
25
|
+
primitive_buffer.fill_rect 0, 0, primitive_buffer.w, primitive_buffer.h,
|
26
|
+
primitive_color(0x000000ff)
|
27
|
+
end
|
28
|
+
|
29
|
+
# Plot a point at (x, y) with the given color (0xRRGGBBAA) on the Bitmap.
|
30
|
+
def point(x, y, color)
|
31
|
+
primitive_buffer[x, y] = primitive_color(color)
|
32
|
+
end
|
33
|
+
|
34
|
+
# Draw a rectangle of size w * h with the top-left corner at (x, y) with
|
35
|
+
# the given color (0xRRGGBBAA).
|
36
|
+
def rect(x, y, w, h, color)
|
37
|
+
primitive_buffer.fill_rect x, y, w, h, primitive_color(color)
|
38
|
+
end
|
39
|
+
|
40
|
+
# Draw a line from (x1, y1) to (x2, y2) with the given color (0xRRGGBBAA).
|
41
|
+
# Optional hash arguments:
|
42
|
+
#
|
43
|
+
# +:antialias+:: If true, smooth the line with antialiasing.
|
44
|
+
def line(x1, y1, x2, y2, color, options=nil)
|
45
|
+
primitive_buffer.draw_line x1, y1, x2, y2,
|
46
|
+
primitive_color(color),
|
47
|
+
(options[:antialias] if options)
|
48
|
+
end
|
49
|
+
|
50
|
+
# Draw a circle centred at (x, y) with the given radius and color.
|
51
|
+
# Optional hash arguments:
|
52
|
+
#
|
53
|
+
# +:outline+:: If true, do not fill the circle, just draw an outline.
|
54
|
+
# +:antialias+:: If true, smooth the edges of the circle with
|
55
|
+
# antialiasing.
|
56
|
+
def circle(x, y, radius, color, options=nil)
|
57
|
+
if options
|
58
|
+
primitive_buffer.draw_circle x, y, radius, primitive_color(color),
|
59
|
+
!options[:outline], options[:antialias]
|
60
|
+
else
|
61
|
+
primitive_buffer.draw_circle x, y, radius, primitive_color(color), true
|
62
|
+
end
|
63
|
+
end
|
64
|
+
|
65
|
+
private
|
66
|
+
|
67
|
+
# Convert hex_color of the form 0xRRGGBBAA to a color value the
|
68
|
+
# primitive_buffer understands.
|
69
|
+
def primitive_color(hex_color)
|
70
|
+
red = (hex_color & 0xff000000) >> 24
|
71
|
+
green = (hex_color & 0x00ff0000) >> 16
|
72
|
+
blue = (hex_color & 0x0000ff00) >> 8
|
73
|
+
alpha = (hex_color & 0x000000ff)
|
74
|
+
primitive_buffer.map_rgba(red, green, blue, alpha)
|
75
|
+
end
|
76
|
+
|
77
|
+
end
|
78
|
+
|
79
|
+
end
|
data/lib/tea/screen.rb
ADDED
@@ -0,0 +1,59 @@
|
|
1
|
+
# This file contains the Screen class.
|
2
|
+
|
3
|
+
require 'sdl'
|
4
|
+
|
5
|
+
require 'tea/m_blitting'
|
6
|
+
require 'tea/m_primitive_drawing'
|
7
|
+
|
8
|
+
#
|
9
|
+
module Tea
|
10
|
+
|
11
|
+
# A Bitmap-like object that displays its contents on the screen when drawn to
|
12
|
+
# and updated.
|
13
|
+
class Screen
|
14
|
+
|
15
|
+
# Video buffer depth.
|
16
|
+
BITS_PER_PIXEL = 32
|
17
|
+
|
18
|
+
# Set or change the screen video mode, giving a width * height screen buffer.
|
19
|
+
def Screen.set_mode(width, height)
|
20
|
+
begin
|
21
|
+
@screen = SDL::Screen.open(width, height, BITS_PER_PIXEL, SDL::SWSURFACE)
|
22
|
+
@set_mode_callbacks.each { |c| c.call }
|
23
|
+
rescue SDL::Error => e
|
24
|
+
raise Tea::Error, e.message, e.backtrace
|
25
|
+
end
|
26
|
+
end
|
27
|
+
|
28
|
+
# Check if Screen.set_mode has been called yet.
|
29
|
+
def Screen.mode_set?
|
30
|
+
@screen ? true : false
|
31
|
+
end
|
32
|
+
|
33
|
+
# Set a proc to be called when Screen.set_mode is called. The proc will be
|
34
|
+
# called after the new screen mode is set. The callback ordering is not
|
35
|
+
# defined, so don't make callbacks that depend on other callbacks being
|
36
|
+
# called first.
|
37
|
+
def Screen.on_set_mode(callback)
|
38
|
+
@set_mode_callbacks << callback
|
39
|
+
end
|
40
|
+
@set_mode_callbacks = []
|
41
|
+
|
42
|
+
# Get the screen width in pixels.
|
43
|
+
def Screen.w; @screen.w; end
|
44
|
+
|
45
|
+
# Get the screen height in pixels.
|
46
|
+
def Screen.h; @screen.h; end
|
47
|
+
|
48
|
+
# Update the screen so that things drawn on it are displayed.
|
49
|
+
def Screen.update; @screen.flip; end
|
50
|
+
|
51
|
+
extend Blitting
|
52
|
+
def Screen.blittable_buffer; @screen; end
|
53
|
+
|
54
|
+
extend PrimitiveDrawing
|
55
|
+
def Screen.primitive_buffer; @screen; end
|
56
|
+
|
57
|
+
end
|
58
|
+
|
59
|
+
end
|
data/lib/tea.rb
ADDED
@@ -0,0 +1,29 @@
|
|
1
|
+
# Tea is a simple 2D game development library for Ruby.
|
2
|
+
|
3
|
+
require 'sdl'
|
4
|
+
|
5
|
+
require 'tea/c_bitmap'
|
6
|
+
require 'tea/c_error'
|
7
|
+
require 'tea/m_event'
|
8
|
+
require 'tea/screen'
|
9
|
+
|
10
|
+
# The Tea module acts as a namespace for all Tea-related objects and
|
11
|
+
# methods.
|
12
|
+
module Tea
|
13
|
+
|
14
|
+
# Initialise Tea. This needs to be called before using any of Tea's
|
15
|
+
# objects or methods.
|
16
|
+
#
|
17
|
+
# May throw Tea::Error if initialisation fails.
|
18
|
+
def Tea.init
|
19
|
+
begin
|
20
|
+
SDL.init(SDL::INIT_VIDEO)
|
21
|
+
|
22
|
+
# Get typed characters from keys when pressed.
|
23
|
+
SDL::Event.enable_unicode
|
24
|
+
rescue SDL::Error => e
|
25
|
+
raise Tea::Error, e.message, e.backtrace
|
26
|
+
end
|
27
|
+
end
|
28
|
+
|
29
|
+
end
|