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
|
=begin
APIs listing that haven't been encountered in previous sample apps:
- merge: Returns a hash containing the contents of two original hashes.
Merge does not allow duplicate keys, so the value of a repeated key
will be overwritten.
For example, if we had two hashes
h1 = { "a" => 1, "b" => 2}
h2 = { "b" => 3, "c" => 3}
and we called the command
h1.merge(h2)
the result would the following hash
{ "a" => 1, "b" => 3, "c" => 3}.
Reminders:
- Hashes: Collection of unique keys and their corresponding values. The value can be found
using their keys.
In this sample app, we're using a hash to create a sprite.
- args.outputs.sprites: An array. The values generate a sprite.
The parameters are [X, Y, WIDTH, HEIGHT, PATH, ANGLE, ALPHA, RED, GREEN, BLUE]
Before continuing with this sample app, it is HIGHLY recommended that you look
at mygame/documentation/05-sprites.md.
- args.inputs.keyboard.key_held.KEY: Determines if a key is being pressed.
For more information about the keyboard, go to mygame/documentation/06-keyboard.md.
- args.inputs.controller_one: Takes input from the controller based on what key is pressed.
For more information about the controller, go to mygame/documentation/08-controllers.md.
- num1.lesser(num2): Finds the lower value of the given options.
=end
# This sample app shows a car moving across the screen. It loops back around if it exceeds the dimensions of the screen,
# and also can be moved in different directions through keyboard input from the user.
# Calls the methods necessary for the game to run successfully.
def tick args
default args
render args.grid, args.outputs, args.state
calc args.state
process_inputs args
end
# Sets default values for the car sprite
# Initialization ||= only happens in the first frame
def default args
args.state.sprite.width = 19
args.state.sprite.height = 10
args.state.sprite.scale = 4
args.state.max_speed = 5
args.state.x ||= 100
args.state.y ||= 100
args.state.speed ||= 1
args.state.angle ||= 0
end
# Outputs sprite onto screen
def render grid, outputs, state
outputs.solids << [grid.rect, 70, 70, 70] # outputs gray background
outputs.sprites << [destination_rect(state), # sets first four parameters of car sprite
'sprites/86.png', # image path of car
state.angle,
opacity, # transparency
saturation,
source_rect(state), # sprite sub division/tile (tile x, y, w, h)
false, false, # don't flip sprites
rotation_anchor]
# also look at the create_sprite helper method
#
# For example:
#
# dest = destination_rect(state)
# source = source_rect(state),
# outputs.sprites << create_sprite(
# 'sprites/86.png',
# x: dest.x,
# y: dest.y,
# w: dest.w,
# h: dest.h,
# angle: state.angle,
# source_x: source.x,
# source_y: source.y,
# source_w: source.w,
# source_h: source.h,
# flip_h: false,
# flip_v: false,
# rotation_anchor_x: 0.7,
# rotation_anchor_y: 0.5
# )
end
# Creates sprite by setting values inside of a hash
def create_sprite path, options = {}
options = {
# dest x, y, w, h
x: 0,
y: 0,
w: 100,
h: 100,
# angle, rotation
angle: 0,
rotation_anchor_x: 0.5,
rotation_anchor_y: 0.5,
# color saturation (red, green, blue), transparency
r: 255,
g: 255,
b: 255,
a: 255,
# source x, y, width, height
source_x: 0,
source_y: 0,
source_w: -1,
source_h: -1,
# flip horiztonally, flip vertically
flip_h: false,
flip_v: false,
}.merge options
[
options[:x], options[:y], options[:w], options[:h], # dest rect keys
path,
options[:angle], options[:a], options[:r], options[:g], options[:b], # angle, color, alpha
options[:source_x], options[:source_y], options[:source_w], options[:source_h], # source rect keys
options[:flip_h], options[:flip_v], # flip
options[:rotation_anchor_x], options[:rotation_anchor_y], # rotation anchor
] # hash keys contain corresponding values
end
# Calls the calc_pos and calc_wrap methods.
def calc state
calc_pos state
calc_wrap state
end
# Changes sprite's position on screen
# Vectors have magnitude and direction, so the incremented x and y values give the car direction
def calc_pos state
state.x += state.angle.vector_x * state.speed # increments x by product of angle's x vector and speed
state.y += state.angle.vector_y * state.speed # increments y by product of angle's y vector and speed
state.speed *= 1.1 # scales speed up
state.speed = state.speed.lesser(state.max_speed) # speed is either current speed or max speed, whichever has a lesser value (ensures that the car doesn't go too fast or exceed the max speed)
end
# The screen's dimensions are 1280x720. If the car goes out of scope,
# it loops back around on the screen.
def calc_wrap state
# car returns to left side of screen if it disappears on right side of screen
# sprite.width refers to tile's size, which is multipled by scale (4) to make it bigger
state.x = -state.sprite.width * state.sprite.scale if state.x - 20 > 1280
# car wraps around to right side of screen if it disappears on the left side
state.x = 1280 if state.x + state.sprite.width * state.sprite.scale + 20 < 0
# car wraps around to bottom of screen if it disappears at the top of the screen
# if you subtract 520 pixels instead of 20 pixels, the car takes longer to reappear (try it!)
state.y = 0 if state.y - 20 > 720 # if 20 pixels less than car's y position is greater than vertical scope
# car wraps around to top of screen if it disappears at the bottom of the screen
state.y = 720 if state.y + state.sprite.height * state.sprite.scale + 20 < 0
end
# Changes angle of sprite based on user input from keyboard or controller
def process_inputs args
# NOTE: increasing the angle doesn't mean that the car will continue to go
# in a specific direction. The angle is increasing, which means that if the
# left key was kept in the "down" state, the change in the angle would cause
# the car to go in a counter-clockwise direction and form a circle (360 degrees)
if args.inputs.keyboard.key_held.left # if left key is pressed
args.state.angle += 2 # car's angle is incremented by 2
# The same applies to decreasing the angle. If the right key was kept in the
# "down" state, the decreasing angle would cause the car to go in a clockwise
# direction and form a circle (360 degrees)
elsif args.inputs.keyboard.key_held.right # if right key is pressed
args.state.angle -= 2 # car's angle is decremented by 2
# Input from a controller can also change the angle of the car
elsif args.inputs.controller_one.left_analog_x_perc != 0
args.state.angle += 2 * args.inputs.controller_one.left_analog_x_perc * -1
end
end
# A sprite's center of rotation can be altered
# Increasing either of these numbers would dramatically increase the
# car's drift when it turns!
def rotation_anchor
[0.7, 0.5]
end
# Sets opacity value of sprite to 255 so that it is not transparent at all
# Change it to 0 and you won't be able to see the car sprite on the screen
def opacity
255
end
# Sets the color of the sprite to white.
def saturation
[255, 255, 255]
end
# Sets definition of destination_rect (used to define the car sprite)
def destination_rect state
[state.x, state.y,
state.sprite.width * state.sprite.scale, # multiplies by 4 to set size
state.sprite.height * state.sprite.scale]
end
# Portion of a sprite (a tile)
# Sub division of sprite is denoted as a rectangle directly related to original size of .png
# Tile is located at bottom left corner within a 19x10 pixel rectangle (based on sprite.width, sprite.height)
def source_rect state
[0, 0, state.sprite.width, state.sprite.height]
end
|