11< html >
22 < head >
3- < title > DragonRuby Game Toolkit - Moving a Sprite </ title >
3+ < title > DragonRuby Game Toolkit - Hello World </ title >
44 < link rel ="stylesheet " href ="//cdnjs.cloudflare.com/ajax/libs/highlight.js/10.0.3/styles/default.min.css " />
55 < script src ="//cdnjs.cloudflare.com/ajax/libs/highlight.js/10.0.3/highlight.min.js "> </ script >
66 < script src ="tutorial.js "> </ script >
77 < link rel ="stylesheet " href ="tutorial.css " />
88 </ head >
99 < 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 >
1114 < div itemscope ="itemscope " itemtype ="tutorial-step " data-step-number ="1 ">
1215 < div itemscope ="itemscope " itemtype ="tutorial-text ">
1316 < 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 >
1628 </ div >
1729 < div itemscope ="itemscope " itemtype ="tutorial-code ">
1830 < pre >
1931 < code class ="language-ruby " itemprop ="text ">
20- # entry point to game
32+ # this is how you define the tick method in DragonRuby
2133 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+ }
2640 end
2741
28- # reset the game on save
42+ # reset the game if we save
2943 $gtk.reset
3044 </ code >
3145 </ pre >
@@ -34,49 +48,31 @@ <h1>Hello World</h1>
3448
3549 < div itemscope ="itemscope " itemtype ="tutorial-step " data-step-number ="2 ">
3650 < 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 >
3961 </ div >
4062 < div itemscope ="itemscope " itemtype ="tutorial-code ">
4163 < pre >
4264 < code class ="language-ruby " itemprop ="text ">
4365 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+ }
7774 end
7875
79- # reset the game on save
8076 $gtk.reset
8177 </ code >
8278 </ pre >
@@ -85,46 +81,205 @@ <h1>Drawing A Sprite</h1>
8581
8682 < div itemscope ="itemscope " itemtype ="tutorial-step " data-step-number ="3 ">
8783 < 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 >
91241 </ div >
92242 < div itemscope ="itemscope " itemtype ="tutorial-code ">
93243 < pre >
94244 < code class ="language-ruby " itemprop ="text ">
95245 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
112263 end
113264
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
116269 end
117270
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+ )
126278
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+ )
128283 end
129284
130285 $gtk.reset
0 commit comments