Reputation: 11
I am very new to Ruby and have been going through a couple of sources to try and learn. I finished Codecadamy's Ruby class and I am about 75% through Learn Ruby the Hard Way. Also I've read about 100 pages of both Eloquent Ruby and the pickaxe Ruby book (but those aren't clicking for me as of yet).
I am trying to make a text based RPG game in Ruby for practice. I decided to recreate Chrono Trigger, as I know the game well and I don't want to take time thinking of characters and stories; just want to practice coding.
I tried to make four simple controls for the player to use, however I am finding it very difficult to incorporate in scenes.
For example I have the control "talk" and I use 'if/else' statements to run the scenes based on what the user inputs. I find myself having to go through endless if/else scenarios if the user types "talk" multiple times.
Below is my code. It's extremely messy as I am a beginner, but if someone could look at it and give me some advice on how to make it work that would be great!
def welcome
puts "Welcome to Chrono Trigger: Ruby Edition!"
puts "Let's discuss the controls to help you become familiar with the game."
puts ""
puts "We are going to break the controls down into categories to help make it easier to understand"
puts "Anytime you get stuck just type 'help' to bring the controls back up."
puts ""
puts "The controls are 'talk' 'action' 'attack' 'flee'."
puts ""
puts "Simple enough? Type 'start' to begin!"
print "> "
response = $stdin.gets.chomp
if response == "start" then chapter_1_start end
end
def crono_next
puts "What should Crono do next?"
@next_task = $stdin.gets.chomp
end
def chapter_1_start
puts "(Bells Ringing)"
puts "\"Crono....Crono...\""
puts "\"Time to get up!\""
puts ""
puts "Crono wakes up from bed."
puts "Crono is standing in the middle of his bedroom"
print "> "
response = $stdin.gets.chomp
if response == "help"
help
elsif response == "action"
puts "Crono closes the curtains."
puts "Then he leaves the room"
chapter_1_start2
elsif response == "talk"
puts "Crono talks to himself"
else
puts "..."
end
end
def chapter_1_start2
def talk
puts "Mom: \"Oh Crono, don't forget to stop by your friend Lucca's house before you head to the Millenial Fair.\""
crono_next
if @next_task == "talk"
puts "Mom: \"I almost forgot. Here's 200 gil to buys some cat food while you're out.\""
crono_next
if @next_task == "talk"
puts "Mom: \"You really should be leaving now Crono\""
chapter_1_start3
elsif @next_task == "action"
puts "Crono pets his cat."
puts "'Meow'"
chapter_1_start3
else
chapter_1_start3
end
elsif @next_task == "action"
action
else
"Mom: \"You really should be leaving now Crono\""
chapter_1_start3
end
end
def action
puts "Crono pets his cat."
puts "'Meow'"
crono_next
if @next_task == "talk"
talk
elsif @next_task == "action"
action
else
"Crono does nothing."
end
end
puts "Crono heads downstairs and sees his mom in the kitchen and his cat in the living room."
crono_next
if @next_task == "talk"
talk
elsif @next_task == "action"
action
else
puts "Let's try that again."
chapter_1_start2
end
end
def chapter_1_start3
puts ""
puts "Crono begins walking away from his house"
puts "If he travels West he will be heading in the direction of Lucca's house."
puts "If he travels East he will be headed to the Millenial Fair."
puts crono_next
def help
puts "What do you need help with? 'controls', 'hints', 'quit'"
print "> "
help_subject = $stdin.gets.chomp
if help_subject == "controls"
puts "The controls are 'talk' 'action' 'attack' 'flee'."
elsif help_subject == "hints"
puts "I got nothing"
elsif help_subject == "quit"
puts "Are you sure you want to quit?(Your game will not be saved)"
print "> "
sure_quit = $stdin.gets.chomp
if sure_quit.include? "y"
exit(0)
else
help
end
else
puts "Guess you didn't really need help after all."
end
end
def talk(person)
@person = person
end
welcome
Upvotes: 0
Views: 1587
Reputation: 5345
Text-based games are actually quite complicated and end up following many of the same logic and design patterns as traditional video games. You may want to google around for guides on game design- there are lots of them and the fundamentals apply to any programming language.
That being said, if you want to continue with your game as it is without getting lost in endless if-statements, you should use classes to manage your scenes.
Every game has a main loop, which is an endless loop which handles 3 main tasks: displaying stuff to the screen, collecting user input, and calculating changes in the game state. That happens over and over again:
#main.rb
scene = Scene.new(:chapter_1)
while true
scene.display
print "> "
action = $stdin.gets.chomp
if command == 'talk'
scene = scene.talk
elsif command == 'action'
scene = scene.action
elsif command = 'attack'
scene = scene.attack
elsif command = 'flee'
scene = scene.flee
else
puts 'unknown command!'
end
end
The scene class basically just holds the text for each scene as well as which actions link which scenes to which other scenes. This structure is called a state machine, and it's the simplest way to keep track of a game's state:
#scene.rb
class Scene
def initialize beginning_state
@state = beginning_state
@scenes = {
chapter_1: [
"Hello and welcome to chapter 1 of my game!",
:ch1_talk,
:ch1_action,
:ch1_attack,
:chapter_2],
ch1_talk: [
"Please stop talking while I'm talking!",
:ch1_talk,
:ch1_action,
:ch1_attack,
:chapter_2],
ch1_action: [
"W-what are you doing?!",
:ch1_talk,
:ch1_action,
:ch1_attack,
:chapter_2],
ch1_attack: [
"Stop, that hurts :c",
:ch1_talk,
:ch1_action,
:ch1_attack,
:chapter_2],
chapter_2: [
"Congratulations, you have entered...\n chapter 2!",
:ch2_talk,
:ch2_action,
:ch2_attack,
:ch2_flee],
ch2_talk: [
"I'm ignoring you",
:ch2_talk,
:ch2_action,
:ch2_attack,
:ch2_flee],
ch2_action: [
"I don't even care",
:ch2_talk,
:ch2_action,
:ch2_attack,
:ch2_flee],
ch2_attack: [
"You're no match for me",
:ch2_talk,
:ch2_action,
:ch2_attack,
:ch2_flee],
ch2_flee: [
"Okay, goodbye!",
:ch2_talk,
:ch2_action,
:ch2_attack,
:ch2_flee],
}
end
def display
puts @scenes[@state][0]
end
def talk
@state = @scenes[@state][1]
end
def action
@state = @scenes[@state][2]
end
def attack
@state = @scenes[@state][3]
end
def flee
@state = @scenes[@state][4]
end
end
Sorry that's a bit complicated, but games are a bit complicated. Also ideally, you would save your scenes in specially-formatted text files and then load them into the game, instead of defining them in source code like I did.
Upvotes: 2