1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
|
# ==========================================================================
# _ _ ________ __ _ _____ _____ _______ ______ _ _ _ _ _ _
# | | | | ____\ \ / / | | |_ _|/ ____|__ __| ____| \ | | | | | |
# | |__| | |__ \ \_/ / | | | | | (___ | | | |__ | \| | | | | |
# | __ | __| \ / | | | | \___ \ | | | __| | . ` | | | | |
# | | | | |____ | | | |____ _| |_ ____) | | | | |____| |\ |_|_|_|_|
# |_| |_|______| |_| |______|_____|_____/ |_| |______|_| \_(_|_|_|_)
#
#
# |
# |
# |
# |
# |
# |
# |
# |
# |
# |
# \ | /
# \ | /
# +
#
# If you are new to the programming language Ruby, then you may find the
# following code a bit overwhelming. This sample is only designed to be
# run interactively (as opposed to being manipulated via source code).
#
# Start up this sample and follow along by visiting:
# https://s3.amazonaws.com/s3.dragonruby.org/dragonruby-gtk-primer.mp4
#
# It is STRONGLY recommended that you work through all the samples before
# looking at the code in this file.
# ==========================================================================
class TutorialOutputs
attr_accessor :solids, :sprites, :labels, :lines, :borders
def initialize
@solids = []
@sprites = []
@labels = []
@lines = []
@borders = []
end
def tick
@solids ||= []
@sprites ||= []
@labels ||= []
@lines ||= []
@borders ||= []
@solids.each { |p| $gtk.args.outputs.reserved << p.solid }
@sprites.each { |p| $gtk.args.outputs.reserved << p.sprite }
@labels.each { |p| $gtk.args.outputs.reserved << p.label }
@lines.each { |p| $gtk.args.outputs.reserved << p.line }
@borders.each { |p| $gtk.args.outputs.reserved << p.border }
end
def clear
@solids.clear
@sprites.clear
@labels.clear
@borders.clear
end
end
def defaults
state.reset_button ||=
state.new_entity(
:button,
label: [1190, 68, "RESTART", -2, 0, 0, 0, 0].label,
background: [1160, 38, 120, 50, 255, 255, 255].solid
)
$gtk.log_level = :off
end
def tick_reset_button
return unless state.hello_dragonruby_confirmed
$gtk.args.outputs.reserved << state.reset_button.background
$gtk.args.outputs.reserved << state.reset_button.label
if inputs.mouse.click && inputs.mouse.click.point.inside_rect?(state.reset_button.background)
restart_tutorial
end
end
def seperator
@seperator = "=" * 80
end
def tick_intro
queue_message "Welcome to the DragonRuby GTK primer! Try typing the
code below and press ENTER:
puts \"Hello DragonRuby!\"
"
end
def tick_hello_dragonruby
return unless console_has? "Hello DragonRuby!"
$gtk.args.state.hello_dragonruby_confirmed = true
queue_message "Well HELLO to you too!
If you ever want to RESTART the tutorial, just click the \"RESTART\"
button in the bottom right-hand corner.
Let's continue shall we? Type the code below and press ENTER:
outputs.solids << [910, 200, 100, 100, 255, 0, 0]
"
end
def tick_explain_solid
return unless $tutorial_outputs.solids.any? {|s| s == [910, 200, 100, 100, 255, 0, 0]}
queue_message "Sweet!
The code: outputs.solids << [910, 200, 100, 100, 255, 0, 0]
Does the following:
1. GET the place where SOLIDS go: outputs.solids
2. Request that a new SOLID be ADDED: <<
3. The DEFINITION of a SOLID is the ARRAY:
[910, 200, 100, 100, 255, 0, 0]
GET ADD X Y WIDTH HEIGHT RED GREEN BLUE
| | | | | | | | |
| | | | | | | | |
outputs.solids << [910, 200, 100, 100, 255, 0, 0]
|_________________________________________|
|
|
ARRAY
Now let's create a blue SOLID. Type:
outputs.solids << [1010, 200, 100, 100, 0, 0, 255]
"
state.explain_solid_confirmed = true
end
def tick_explain_solid_blue
return unless state.explain_solid_confirmed
return unless $tutorial_outputs.solids.any? {|s| s == [1010, 200, 100, 100, 0, 0, 255]}
state.explain_solid_blue_confirmed = true
queue_message "And there is our blue SOLID!
The ARRAY is the MOST important thing in DragonRuby GTK.
Let's create a SPRITE using an ARRAY:
outputs.sprites << [1110, 200, 100, 100, 'sprites/dragon_fly_0.png']
"
end
def tick_explain_tick_count
return unless $tutorial_outputs.sprites.any? {|s| s == [1110, 200, 100, 100, 'sprites/dragon_fly_0.png']}
return if $tutorial_outputs.labels.any? {|l| l == [1210, 200, state.tick_count, 255, 255, 255]}
state.explain_tick_count_confirmed = true
queue_message "Look at the cute little dragon!
We can create a LABEL with ARRAYS too. Let's create a LABEL showing
THE PASSAGE OF TIME, which is called TICK_COUNT.
outputs.labels << [1210, 200, state.tick_count, 0, 255, 0]
"
end
def tick_explain_mod
return unless $tutorial_outputs.labels.any? {|l| l == [1210, 200, state.tick_count, 0, 255, 0]}
state.explain_mod_confirmed = true
queue_message "
The code: outputs.labels << [1210, 200, state.tick_count, 0, 255, 0]
Does the following:
1. GET the place where labels go: outputs.labels
2. Request that a new label be ADDED: <<
3. The DEFINITION of a LABEL is the ARRAY:
[1210, 200, state.tick_count, 0, 255, 0]
GET ADD X Y TEXT RED GREEN BLUE
| | | | | | | |
| | | | | | | |
outputs.labels << [1210, 200, state.tick_count, 0, 255, 0]
|______________________________________________|
|
|
ARRAY
Now let's do some MATH, save the result to STATE, and create a LABEL:
state.sprite_frame = state.tick_count.idiv(4).mod(6)
outputs.labels << [1210, 170, state.sprite_frame, 0, 255, 0]
Type the lines above (pressing ENTER after each line).
"
end
def tick_explain_string_interpolation
return unless state.explain_mod_confirmed
return unless state.sprite_frame == state.tick_count.idiv(4).mod(6)
return unless $tutorial_outputs.labels.any? {|l| l == [1210, 170, state.sprite_frame, 0, 255, 0]}
queue_message "Here is what the mathematical computation you just typed does:
1. Create an item of STATE named SPRITE_FRAME: state.sprite_frame =
2. Set this SPRITE_FRAME to the PASSAGE OF TIME (tick_count),
DIVIDED EVENLY (idiv) into 4,
and then compute the REMAINDER (mod) of 6.
STATE SPRITE_FRAME PASSAGE OF HOW LONG HOW MANY
| | TIME TO SHOW IMAGES
| | | AN IMAGE TO FLIP THROUGH
| | | | |
state.sprite_frame = state.tick_count.idiv(4).mod(6)
| |
| +- REMAINDER OF DIVIDE
DIVIDE EVENLY
(NO DECIMALS)
With the information above, we can animate a SPRITE
using STRING INTERPOLATION: \#{}
which creates a unique SPRITE_PATH:
state.sprite_path = \"sprites/dragon_fly_\#{state.sprite_frame}.png\"
outputs.labels << [910, 330, \"path: \#{state.sprite_path}\", 0, 255, 0]
outputs.sprites << [910, 330, 370, 370, state.sprite_path]
Type the lines above (pressing ENTER after each line).
"
end
def tick_reprint_on_error
return unless console.last_command_errored
puts $gtk.state.messages.last
puts "\nWhoops! Try again."
console.last_command_errored = false
end
def tick_evals
state.evals ||= []
if console.last_command && (console.last_command.start_with?("outputs.") || console.last_command.start_with?("state."))
state.evals << console.last_command
console.last_command = nil
end
state.evals.each do |l|
Kernel.eval l
end
rescue Exception => e
state.evals = state.evals[0..-2]
end
$tutorial_outputs ||= TutorialOutputs.new
def tick args
$gtk.log_level = :off
defaults
console.show
$tutorial_outputs.clear
$tutorial_outputs.solids << [900, 37, 480, 700, 0, 0, 0, 255]
$tutorial_outputs.borders << [900, 37, 380, 683, 255, 255, 255]
tick_evals
$tutorial_outputs.tick
tick_intro
tick_hello_dragonruby
tick_reset_button
tick_explain_solid
tick_explain_solid_blue
tick_reprint_on_error
tick_explain_tick_count
tick_explain_mod
tick_explain_string_interpolation
end
def console
$gtk.console
end
def queue_message message
$gtk.args.state.messages ||= []
return if $gtk.args.state.messages.include? message
$gtk.args.state.messages << message
last_three = [$gtk.console.log[-3], $gtk.console.log[-2], $gtk.console.log[-1]].reject_nil
$gtk.console.log.clear
puts seperator
$gtk.console.log += last_three
puts seperator
puts message
puts seperator
end
def console_has? message
console.log.map(&:upcase).include? "#{message.upcase}\n"
end
def restart_tutorial
$tutorial_outputs.clear
$gtk.console.log.clear
$gtk.reset
puts "Starting the tutorial over!"
end
def state
$gtk.args.state
end
def inputs
$gtk.args.inputs
end
def outputs
$tutorial_outputs
end
|