1
1
< html >
2
2
< head >
3
- < title > DragonRuby Game Toolkit - Moving a Sprite </ title >
3
+ < title > DragonRuby Game Toolkit - Hello World </ title >
4
4
< link rel ="stylesheet " href ="//cdnjs.cloudflare.com/ajax/libs/highlight.js/10.0.3/styles/default.min.css " />
5
5
< script src ="//cdnjs.cloudflare.com/ajax/libs/highlight.js/10.0.3/highlight.min.js "> </ script >
6
6
< script src ="tutorial.js "> </ script >
7
7
< link rel ="stylesheet " href ="tutorial.css " />
8
8
</ head >
9
9
< body >
10
- < h1 > DragonRuby Game Toolkit - Moving a Sprite</ h1 >
10
+ < h1 > Hey Listen!</ h1
11
+ < p >
12
+ You can try out this tutorial interactively < a href ="http://fiddle.dragonruby.org?tutorial=http://fiddle.dragonruby.org/tutorial-hello-world.html " target ="_blank "> here</ a > .
13
+ </ p >
11
14
< div itemscope ="itemscope " itemtype ="tutorial-step " data-step-number ="1 ">
12
15
< div itemscope ="itemscope " itemtype ="tutorial-text ">
13
16
< h1 > Hello World</ h1 >
14
- In this tutorial, we'll cover how to move a sprite. We'll start off with
15
- a empty canvas with a dark gray color.
17
+ < p >
18
+ In this tutorial, we'll cover how to move a player around
19
+ using the keyboard.
20
+ </ p >
21
+
22
+ < p >
23
+ DragonRuby requires you to define a < code > method</ code > called < code > tick</ code > . This < code > tick</ code >
24
+ method is called on your behalf at the rate of sixty times per second.
25
+ </ p >
26
+
27
+ < p > The code you're currently looking at renders a label to the screen and prints the current frame.</ p >
16
28
</ div >
17
29
< div itemscope ="itemscope " itemtype ="tutorial-code ">
18
30
< pre >
19
31
< code class ="language-ruby " itemprop ="text ">
20
- # entry point to game
32
+ # this is how you define the tick method in DragonRuby
21
33
def tick args
22
- # set the game's background color
23
- # try changing these numbers and seeing how
24
- # the background color changes
25
- args.outputs.background_color = [40, 44, 52]
34
+ # this is how a label is rendered to the screen
35
+ args.outputs.labels < < {
36
+ x: 30,
37
+ y: 30,
38
+ text: args.state.tick_count
39
+ }
26
40
end
27
41
28
- # reset the game on save
42
+ # reset the game if we save
29
43
$gtk.reset
30
44
</ code >
31
45
</ pre >
@@ -34,49 +48,31 @@ <h1>Hello World</h1>
34
48
35
49
< div itemscope ="itemscope " itemtype ="tutorial-step " data-step-number ="2 ">
36
50
< div itemscope ="itemscope " itemtype ="tutorial-text ">
37
- < h1 > Drawing A Sprite</ h1 >
38
- Here is how you add a sprite to the screen.
51
+ < h1 > Rendering a Square</ h1 >
52
+ < p >
53
+ Now that you have a < code > tick</ code > method defined. Let's render a green square to the screen.
54
+ This will represent your player character.
55
+ </ p >
56
+ < p >
57
+ For rendering < code > labels</ code > , we use < code > args.outputs.labels</ code > . To render < code > sprites</ code > , we
58
+ use < code > args.outputs.sprites</ code > . A sprite needs to provide its < code > x</ code > location, its < code > y</ code > location,
59
+ its < code > w</ code > (width), its < code > h</ code > (height), and a < code > path</ code > (file path for the image).
60
+ </ p >
39
61
</ div >
40
62
< div itemscope ="itemscope " itemtype ="tutorial-code ">
41
63
< pre >
42
64
< code class ="language-ruby " itemprop ="text ">
43
65
def tick args
44
- # add a sprite
45
- # try change these numbers to see
46
- # how the sprite changes
47
- args.outputs.sprites < < [
48
- 0, # X
49
- 0, # Y
50
- 20, # W
51
- 20, # H
52
- 'sprites/square-green.png', # PATH
53
- ]
54
-
55
- # list of sprites you have availble to you:
56
- # colors of the rainbow ROY G BIV.
57
- # - sprites/square-red.png
58
- # - sprites/square-orange.png
59
- # - sprites/square-yellow.png
60
- # - sprites/square-green.png
61
- # - sprites/square-blue.png
62
- # - sprites/square-indigo.png
63
- # - sprites/square-violet.png
64
- # - sprites/square-black.png
65
- # - sprites/square-white.png
66
- # - sprites/circle-red.png
67
- # - sprites/circle-orange.png
68
- # - sprites/circle-yellow.png
69
- # - sprites/circle-green.png
70
- # - sprites/circle-blue.png
71
- # - sprites/circle-indigo.png
72
- # - sprites/circle-violet.png
73
- # - sprites/circle-black.png
74
- # - sprites/circle-white.png
75
-
76
- args.outputs.background_color = [40, 44, 52]
66
+ # this is how a sprite is rendered to the screen
67
+ args.outputs.sprites < < {
68
+ x: 0,
69
+ y: 0,
70
+ w: 16,
71
+ h: 16,
72
+ path: 'sprites/square/green.png'
73
+ }
77
74
end
78
75
79
- # reset the game on save
80
76
$gtk.reset
81
77
</ code >
82
78
</ pre >
@@ -85,46 +81,205 @@ <h1>Drawing A Sprite</h1>
85
81
86
82
< div itemscope ="itemscope " itemtype ="tutorial-step " data-step-number ="3 ">
87
83
< div itemscope ="itemscope " itemtype ="tutorial-text ">
88
- < h1 > Moving The Sprite</ h1 >
89
- The < code > tick</ code > method is executed < code > 60</ code > times a second. To
90
- store the location of a sprite accross frames, we need to store it in < code > args.state</ code > .
84
+ < h1 > Storing Variables</ h1 >
85
+ < p >
86
+ We have to store the player's position over time. We do this using DragonRuby's < code > args.state</ code >
87
+ function.
88
+ </ p >
89
+ < p >
90
+ Take a look at the code to see how we define the player's properties as < code > state</ code > variables.
91
+ You'll notice the use of the < code > ||=</ code > symbol (it's referred to as "or equals"). This symbol tells
92
+ DragonRuby to < i > only</ i > set a < code > state</ code > property if it's never been set before.
93
+ </ p >
94
+ < p >
95
+ We will update the player's < code > x</ code > position one time every tick. You'll see the player move
96
+ across the screen.
97
+ </ p >
98
+ </ div >
99
+ < div itemscope ="itemscope " itemtype ="tutorial-code ">
100
+ < pre >
101
+ < code class ="language-ruby " itemprop ="text ">
102
+ def tick args
103
+ # set the player's state
104
+ # only set the player's starting properties
105
+ # once using the ||= operator.
106
+ args.state.player.x ||= 0
107
+ args.state.player.y ||= 0
108
+ args.state.player.w ||= 16
109
+ args.state.player.h ||= 16
110
+
111
+ args.outputs.sprites < < {
112
+ x: args.state.player.x,
113
+ y: args.state.player.y,
114
+ w: args.state.player.w,
115
+ h: args.state.player.h,
116
+ path: 'sprites/square/green.png'
117
+ }
118
+
119
+ # update the players x location once every tick
120
+ args.state.player.x += 2
121
+ end
122
+
123
+ $gtk.reset
124
+ </ code >
125
+ </ pre >
126
+ </ div >
127
+ </ div >
128
+
129
+ < div itemscope ="itemscope " itemtype ="tutorial-step " data-step-number ="4 ">
130
+ < div itemscope ="itemscope " itemtype ="tutorial-text ">
131
+ < h1 > Keyboard Input</ h1 >
132
+ < p >
133
+ The player automatically moves to the right every frame, but we want to control
134
+ the player's movement using the keyboard.
135
+ </ p >
136
+ < p >
137
+ We'll use a conditional statement called an < code > if</ code > statement to only move the player
138
+ if we have held down the < code > right</ code > arrow key. DragonRuby provides all keyboard data
139
+ via < code > args.inputs.keyboard</ code > .
140
+ </ p >
141
+ </ div >
142
+ < div itemscope ="itemscope " itemtype ="tutorial-code ">
143
+ < pre >
144
+ < code class ="language-ruby " itemprop ="text ">
145
+ def tick args
146
+ args.state.player.x ||= 0
147
+ args.state.player.y ||= 0
148
+ args.state.player.w ||= 16
149
+ args.state.player.h ||= 16
150
+
151
+ args.outputs.sprites < < {
152
+ x: args.state.player.x,
153
+ y: args.state.player.y,
154
+ w: args.state.player.w,
155
+ h: args.state.player.h,
156
+ path: 'sprites/square/green.png'
157
+ }
158
+
159
+ # update the players x location only if ~right~
160
+ # is pressed or held on the keyboard
161
+ if args.inputs.keyboard.right
162
+ args.state.player.x += 2
163
+ end
164
+ end
165
+
166
+ $gtk.reset
167
+ </ code >
168
+ </ pre >
169
+ </ div >
170
+ </ div >
171
+
172
+ < div itemscope ="itemscope " itemtype ="tutorial-step " data-step-number ="5 ">
173
+ < div itemscope ="itemscope " itemtype ="tutorial-text ">
174
+ < h1 > Keyboard Input All Directions</ h1 >
175
+ < p >
176
+ We use multiple conditional statements, called < code > if/elsif</ code > conditionals,
177
+ to handle all keyboard input.
178
+ </ p >
179
+ < p >
180
+ We'll use a conditional statement called an < code > if</ code > statement to only move the player
181
+ if we have held down the < code > right</ code > arrow key. DragonRuby provides all keyboard data
182
+ via < code > args.inputs.keyboard</ code > .
183
+ </ p >
184
+ </ div >
185
+ < div itemscope ="itemscope " itemtype ="tutorial-code ">
186
+ < pre >
187
+ < code class ="language-ruby " itemprop ="text ">
188
+ def tick args
189
+ args.state.player.x ||= 0
190
+ args.state.player.y ||= 0
191
+ args.state.player.w ||= 16
192
+ args.state.player.h ||= 16
193
+
194
+ args.outputs.sprites < < {
195
+ x: args.state.player.x,
196
+ y: args.state.player.y,
197
+ w: args.state.player.w,
198
+ h: args.state.player.h,
199
+ path: 'sprites/square/green.png'
200
+ }
201
+
202
+ if args.inputs.keyboard.right
203
+ # update the players x location only if
204
+ # ~right~ is pressed or held on the keyboard
205
+ args.state.player.x += 2
206
+ elsif args.inputs.keyboard.left
207
+ # ~left~ is pressed or held on the keyboard
208
+ args.state.player.x -= 2
209
+ end
210
+
211
+ if args.inputs.keyboard.up
212
+ # ~up~ is pressed or held on the keyboard
213
+ args.state.player.y += 2
214
+ elsif args.inputs.keyboard.down
215
+ # ~down~ is pressed or held on the keyboard
216
+ args.state.player.y -= 2
217
+ end
218
+ end
219
+
220
+ $gtk.reset
221
+ </ code >
222
+ </ pre >
223
+ </ div >
224
+ </ div >
225
+
226
+ < div itemscope ="itemscope " itemtype ="tutorial-step " data-step-number ="6 ">
227
+ < div itemscope ="itemscope " itemtype ="tutorial-text ">
228
+ < h1 > Out of Bounds</ h1 >
229
+ < p >
230
+ Finally, we make sure the player can't go outside of the play
231
+ area which is defined in DragonRuby via < code > args.grid</ code > .
232
+ </ p >
233
+ < p >
234
+ We use a combination of < code > args.grid</ code > and a mathematical
235
+ function called < code > clamp</ code > to make sure the player's
236
+ properties are "clamped" to a minimum and maximum value.
237
+ </ p >
238
+ < p >
239
+ Boom. You've just learned how to move a player around. Congrats.
240
+ </ p >
91
241
</ div >
92
242
< div itemscope ="itemscope " itemtype ="tutorial-code ">
93
243
< pre >
94
244
< code class ="language-ruby " itemprop ="text ">
95
245
def tick args
96
- # initialize the x location once
97
- # using Ruby's ||= operator
98
- args.state.x ||= 0
99
- args.state.y ||= 0
100
-
101
- # every tick, increment the location
102
- # of the sprite by 1
103
- args.state.x += 1
104
- args.state.y += 1
105
-
106
- # if the sprite is off the screen
107
- # move it back to the original position
108
- # the size of this canvas is
109
- # 160 pixels by 90 pixels
110
- if args.state.x > 160
111
- args.state.x = -10
246
+ args.state.player.x ||= 0
247
+ args.state.player.y ||= 0
248
+ args.state.player.w ||= 16
249
+ args.state.player.h ||= 16
250
+
251
+ args.outputs.sprites < < {
252
+ x: args.state.player.x,
253
+ y: args.state.player.y,
254
+ w: args.state.player.w,
255
+ h: args.state.player.h,
256
+ path: 'sprites/square/green.png'
257
+ }
258
+
259
+ if args.inputs.keyboard.right
260
+ args.state.player.x += 2
261
+ elsif args.inputs.keyboard.left
262
+ args.state.player.x -= 2
112
263
end
113
264
114
- if args.state.y > 90
115
- args.state.y = -10
265
+ if args.inputs.keyboard.up
266
+ args.state.player.y += 2
267
+ elsif args.inputs.keyboard.down
268
+ args.state.player.y -= 2
116
269
end
117
270
118
- # render the sprite based on state
119
- args.outputs.sprites < < [
120
- args.state.x, # X
121
- args.state.y, # Y
122
- 20, # W
123
- 20, # H
124
- 'sprites/square-green.png', # PATH
125
- ]
271
+ # make sure the player's x and y position
272
+ # are clamped to the the grid's minimum and
273
+ # maximum width and height
274
+ args.state.player.x = args.state.player.x.clamp(
275
+ args.grid.left,
276
+ args.grid.right - args.state.player.w
277
+ )
126
278
127
- args.outputs.background_color = [40, 44, 52]
279
+ args.state.player.y = args.state.player.y.clamp(
280
+ args.grid.bottom,
281
+ args.grid.top - args.state.player.h
282
+ )
128
283
end
129
284
130
285
$gtk.reset
0 commit comments