【问题标题】:Making RPG text based game in Ruby. How to store and run controls and scenes?用 Ruby 制作基于文本的 RPG 游戏。如何存储和运行控件和场景?
【发布时间】:2019-07-11 00:45:14
【问题描述】:

我对 Ruby 非常陌生,并且已经通过一些资源来尝试和学习。我完成了 Codecadamy 的 Ruby 课程,并且通过 Learn Ruby the Hard Way 完成了大约 75%。此外,我还阅读了大约 100 页的 Eloquent Ruby 和 pickaxe Ruby 书(但到目前为止我还没有点击)。

我正在尝试用 Ruby 制作一个基于文本的 RPG 游戏以供练习。我决定重新制作《时空之轮》,因为我对游戏非常了解,而且我不想花时间思考角色和故事;只是想练习编码。

我尝试制作四个简单的控件供玩家使用,但我发现很难融入场景中。

例如,我有“谈话”控件,并使用“if/else”语句根据用户输入的内容运行场景。如果用户多次键入“talk”,我发现自己不得不经历无穷无尽的 if/else 场景。

下面是我的代码。因为我是初学者,所以它非常混乱,但是如果有人可以看看它并就如何使它工作给我一些建议,那就太好了!

---------欢迎方法------------

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

【问题讨论】:

  • 请将帖子限制在一个指向您代码特定区域的特定问题
  • 关于工作代码的问题更适合codereview.stackexchange.com,但如果不加紧一些,我不会在那里问这个问题。这有点像“代码转储”,但如果它专注于一小部分代码,那可能是一个很好的问题。
  • 很抱歉!我是社区和编程新手,对此我深表歉意。
  • @Caleb 欢迎来到 SO,不用担心。

标签: ruby


【解决方案1】:

基于文本的游戏实际上非常复杂,并且最终遵循许多与传统视频游戏相同的逻辑和设计模式。您可能想四处搜索有关游戏设计的指南——其中有很多,而且基础知识适用于任何编程语言。

话虽如此,如果您想继续您的游戏而不迷失在无休止的 if 语句中,您应该使用类来管理您的场景。

每个游戏都有一个主循环,这是一个处理 3 个主要任务的无限循环:在屏幕上显示内容、收集用户输入以及计算游戏状态的变化。这种情况一遍又一遍地发生:

#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

场景类基本上只保存每个场景的文本以及哪些动作将哪些场景链接到哪些其他场景。这种结构称为状态机,它是跟踪游戏状态的最简单方法:

#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

抱歉,这有点复杂,但游戏有点复杂。同样理想的是,您可以将场景保存在特殊格式的文本文件中,然后将它们加载到游戏中,而不是像我那样在源代码中定义它们。

【讨论】:

  • 非常感谢您抽出宝贵时间对此发表评论!是的,我同意这对于我现在的理解来说有点太复杂了,但是它为我提供了关于如何继续我的项目的深刻见解。您在示例中使用的场景是否被视为符号?组成看起来类似于没有值的哈希。
  • 很高兴为您提供帮助!是的,我正在使用放入数组的符号。散列通常使用符号作为它们的键,因此它们在这里看起来相似是有道理的。附:欢迎来到 StackOverflow 和编程世界:
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 2015-09-10
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2012-08-28
  • 1970-01-01
相关资源
最近更新 更多