summaryrefslogtreecommitdiffhomepage
path: root/samples/99_genre_rpg_narrative/choose_your_own_adventure/app/main.rb
blob: 22faad11033546dea1d54913d273d9788b7b2393 (plain)
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