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
|
=begin
Reminders:
- Hashes: Collection of unique keys and their corresponding values. The values can be found
using their keys.
In this sample app, the decisions needed for the game are stored in a hash. In fact, the
decision.rb file contains hashes inside of other hashes!
Each option is a key in the first hash, but also contains a hash (description and
decision being its keys) as its value.
Go into the decision.rb file and take a look before diving into the code below.
- args.outputs.labels: An array. The values generate a label.
The parameters are [X, Y, TEXT, SIZE, ALIGNMENT, RED, GREEN, BLUE, ALPHA, FONT STYLE]
For more information about labels, go to mygame/documentation/02-labels.md.
- args.keyboard.key_down.KEY: Determines if a key is in the down state or pressed down.
For more information about the keyboard, go to mygame/documentation/06-keyboard.md.
- String interpolation: uses #{} syntax; everything between the #{ and the } is evaluated
as Ruby code, and the placeholder is replaced with its corresponding value or result.
=end
# This sample app provides users with a story and multiple decisions that they can choose to make.
# Users can make a decision using their keyboard, and the story will move forward based on user choices.
# The decisions available to users are stored in the decision.rb file.
# We must have access to it for the game to function properly.
GAME_FILE = 'app/decision.rb' # found in app folder
require GAME_FILE # require used to load another file, import class/method definitions
# Instructions are given using labels to users if they have not yet set up their story in the decision.rb file.
# Otherwise, the game is run.
def tick args
if !args.state.loaded && !respond_to?(:game) # if game is not loaded and not responding to game symbol's method
args.labels << [640, 370, 'Hey there! Welcome to Four Decisions.', 0, 1] # a welcome label is shown
args.labels << [640, 340, 'Go to the file called decision.rb and tell me your story.', 0, 1]
elsif respond_to?(:game) # otherwise, if responds to game
args.state.loaded = true
tick_game args # calls tick_game method, runs game
end
if args.state.tick_count.mod_zero? 60 # update every 60 frames
t = args.gtk.ffi_file.mtime GAME_FILE # mtime returns modification time for named file
if t != args.state.mtime
args.state.mtime = t
require GAME_FILE # require used to load file
args.state.game_definition = nil # game definition and decision are empty
args.state.decision_id = nil
end
end
end
# Runs methods needed for game to function properly
# Creates a rectangular border around the screen
def tick_game args
defaults args
args.borders << args.grid.rect
render_decision args
process_inputs args
end
# Sets default values and uses decision.rb file to define game and decision_id
# variable using the starting decision
def defaults args
args.state.game_definition ||= game
args.state.decision_id ||= args.state.game_definition[:starting_decision]
end
# Outputs the possible decision descriptions the user can choose onto the screen
# as well as what key to press on their keyboard to make their decision
def render_decision args
decision = current_decision args
# text is either the value of decision's description key or warning that no description exists
args.labels << [640, 360, decision[:description] || "No definition found for #{args.state.decision_id}. Please update decision.rb.", 0, 1] # uses string interpolation
# All decisions are stored in a hash
# The descriptions output onto the screen are the values for the description keys of the hash.
if decision[:option_one]
args.labels << [10, 360, decision[:option_one][:description], 0, 0] # option one's description label
args.labels << [10, 335, "(Press 'left' on the keyboard to select this decision)", -5, 0] # label of what key to press to select the decision
end
if decision[:option_two]
args.labels << [1270, 360, decision[:option_two][:description], 0, 2] # option two's description
args.labels << [1270, 335, "(Press 'right' on the keyboard to select this decision)", -5, 2]
end
if decision[:option_three]
args.labels << [640, 45, decision[:option_three][:description], 0, 1] # option three's description
args.labels << [640, 20, "(Press 'down' on the keyboard to select this decision)", -5, 1]
end
if decision[:option_four]
args.labels << [640, 700, decision[:option_four][:description], 0, 1] # option four's description
args.labels << [640, 675, "(Press 'up' on the keyboard to select this decision)", -5, 1]
end
end
# Uses keyboard input from the user to make a decision
# Assigns the decision as the value of the decision_id variable
def process_inputs args
decision = current_decision args # calls current_decision method
if args.keyboard.key_down.left! && decision[:option_one] # if left key pressed and option one exists
args.state.decision_id = decision[:option_one][:decision] # value of option one's decision hash key is set to decision_id
end
if args.keyboard.key_down.right! && decision[:option_two] # if right key pressed and option two exists
args.state.decision_id = decision[:option_two][:decision] # value of option two's decision hash key is set to decision_id
end
if args.keyboard.key_down.down! && decision[:option_three] # if down key pressed and option three exists
args.state.decision_id = decision[:option_three][:decision] # value of option three's decision hash key is set to decision_id
end
if args.keyboard.key_down.up! && decision[:option_four] # if up key pressed and option four exists
args.state.decision_id = decision[:option_four][:decision] # value of option four's decision hash key is set to decision_id
end
end
# Uses decision_id's value to keep track of current decision being made
def current_decision args
args.state.game_definition[:decisions][args.state.decision_id] || {} # either has value or is empty
end
# Resets the game.
$gtk.reset
|