Warning: file_get_contents(/data/phpspider/zhask/data//catemap/9/java/369.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181

Warning: file_get_contents(/data/phpspider/zhask/data//catemap/9/three.js/2.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Java 如何设计一个易于扩展的游戏任务系统?_Java_Php_Oop_Database Design - Fatal编程技术网

Java 如何设计一个易于扩展的游戏任务系统?

Java 如何设计一个易于扩展的游戏任务系统?,java,php,oop,database-design,Java,Php,Oop,Database Design,解释 假设我们有多个任务,完成某项任务后奖励玩家。以下示例显示了用户任务: Name: Get a high score of 100 Requirement: Score of 100 Reward: 10 Coins Name: Get a high score of 5000 Requirement: Score of 5000 Reward: 10 Diamonds Name: Destroy 20 ships Requirement: Destroy 20 ships Reward

解释

假设我们有多个任务,完成某项任务后奖励玩家。以下示例显示了用户任务:

Name: Get a high score of 100
Requirement: Score of 100
Reward: 10 Coins

Name: Get a high score of 5000
Requirement: Score of 5000
Reward: 10 Diamonds

Name: Destroy 20 ships
Requirement: Destroy 20 ships
Reward: 5 Diamonds

Name: Reach level 5
Requirement: Level 5
Reward: 20 Coins, 10 Diamonds
然后我创建以下逻辑:

创建一个名为“Quest”的超类。 为每个任务创建一个子类;继承“任务”超类。 使用多态性,我们调用“CheckForCompletion”方法来检查任务需求是否得到满足。如果是这样,用户将获得奖励

问题

我的问题是我是否创建了一个名为“任务”的数据库表,并将上面的每个任务存储在表中

任务表数据示例: 名称:摧毁20艘船 要求:{“销毁”,“20”} 奖励:{“钻石”,“5”} 如果是这样,将每个任务加载到相应的类中的最佳方法是什么

我是否为每个任务创建一个类而不创建任务表?如果是这样的话,我怎么知道用户何时完成任务,这样用户就不会获得两次奖励

我知道我可以创建一个表并存储必要的需求。然后让一个类包含一堆if语句来执行正确的代码,但我觉得这并不正确。我要问的是;有更好的方法吗

谢谢

编辑1:

每个任务可以有多个需求。例如:摧毁5艘船,杀死10个单位,得分1000等

为了进一步解释want,我想消除if语句。我不想做这样的陈述

if (score == 100)
   //process
else if (ships_destroyed == 5)
   //process
else if (level == 5)
   //process
else if (ships_destroyed == 5 && units_killed == 10 && score == 1000)
   //process

我希望消除这个过程,因为我可能有数百个任务,我不认为它扩展得足够容易。有更好的方法吗?

我有类似的要求:在游戏中添加成就/徽章

你应该考虑:

  • 你会有什么样的先决条件
  • 你有什么样的奖励
  • 先决条件: 若前提条件很简单,比如“摧毁5艘船”,那个么很容易将其存储到数据库中。如果它是复杂的,比如“摧毁5艘船和10个单位”,那么它不是一个前提条件的平面结构

    所以,我可以建议你

  • 任务描述表:id、名称、描述等
  • 先决条件表:任务id,类型('摧毁商店','赢得战斗'…),数量(5,10)
  • 奖励表:任务id、金钱类型、金额。如果每个任务只有一种奖励类型,那么哪些数据可以移动到第一个表中
  • 如何检查每个条件也是一个问题。特别是,如果你想要很多的话。 其中一个可能的解决方案是添加一些触发器定义。比如“用户刚刚摧毁了飞船”,“用户刚刚赢得了战斗”。并为每个任务定义可以触发它的触发器类型。这些信息也可以存储在单独的表中

    UPD: 要检查每个前提条件,每个类型应该有一个java类

    interface Precondition {
        String type()
        boolean check(Map<String, Object> config, Long userId);
    }
    
    class DestroyShipPrecondition{
        public String type() {
            return "destroy_ship"
        }
    
        public boolean check(Map<String, Object> config, Long userId){
            Long expectdAmount = config.get("amount");
            Long realAmount = getDestroyedShipsByUser(userId);
            return expectedAmount<=realAmount;
        }      
    }
    

    我有类似的要求:在游戏中添加成就/徽章

    你应该考虑:

  • 你会有什么样的先决条件
  • 你有什么样的奖励
  • 先决条件: 若前提条件很简单,比如“摧毁5艘船”,那个么很容易将其存储到数据库中。如果它是复杂的,比如“摧毁5艘船和10个单位”,那么它不是一个前提条件的平面结构

    所以,我可以建议你

  • 任务描述表:id、名称、描述等
  • 先决条件表:任务id,类型('摧毁商店','赢得战斗'…),数量(5,10)
  • 奖励表:任务id、金钱类型、金额。如果每个任务只有一种奖励类型,那么哪些数据可以移动到第一个表中
  • 如何检查每个条件也是一个问题。特别是,如果你想要很多的话。 其中一个可能的解决方案是添加一些触发器定义。比如“用户刚刚摧毁了飞船”,“用户刚刚赢得了战斗”。并为每个任务定义可以触发它的触发器类型。这些信息也可以存储在单独的表中

    UPD: 要检查每个前提条件,每个类型应该有一个java类

    interface Precondition {
        String type()
        boolean check(Map<String, Object> config, Long userId);
    }
    
    class DestroyShipPrecondition{
        public String type() {
            return "destroy_ship"
        }
    
        public boolean check(Map<String, Object> config, Long userId){
            Long expectdAmount = config.get("amount");
            Long realAmount = getDestroyedShipsByUser(userId);
            return expectedAmount<=realAmount;
        }      
    }
    

    你的问题有几个相关的方面——和往常一样,答案是“视情况而定”

    首先,我建议不要将你的“任务”类划分为子类——当然,这不是黑白的,但总的来说,我赞成

    如果您确信游戏机制不会改变,我就不必为数据库表操心了——我会在您的编程语言(Java或PHP)中使用常量。从开发和性能的角度来看,在数据库中查找静态数据是非常昂贵的

    如果你认为在调整游戏时这些数据可能需要改变,那么这可能太有限了——每次你想调整任务奖励的时候都要做一个完整的构建会让你很难获得正确的平衡。在这种情况下,我会使用一个配置文件——数据会发生变化,但只有在游戏开始时,而不是在游戏运行时

    如果您的游戏机制要求在游戏期间更改奖励,并且这是一个多人游戏,那么您可能需要使用数据库


    最后,大多数游戏引擎都满足了这种需求——也许你的计划有些过火,但值得考虑。

    你的问题有几个相关方面——和往常一样,答案是“视情况而定”

    首先,我建议不要将你的“任务”类划分为子类——当然,这不是黑白的,但总的来说,我赞成

    如果您确信游戏机制不会改变,我就不必为数据库表操心了——我会在您的编程语言(Java或PHP)中使用常量。从开发和性能的角度来看,在数据库中查找静态数据是非常昂贵的

    如果你认为在调整游戏时这些数据可能需要改变,那么这可能太有限了——每次你想调整任务奖励时都要进行完整的构建,这将很难达到平衡
    public class Game {
      public static class GameState {
        public int playerscore = 1750;
      }
    
      public enum Quest {
        FIVE_HUNDRED_PT(
          (GameState gamestate) -> gamestate.playerscore > 500,
          () -> Game.trigger500pointHurray()
        ),
        FIVE_THOUSAND_PT(
          (GameState gamestate) -> gamestate.playerscore > 5000,
          () -> Game.trigger5000pointHurray()
        );
    
        private final Function<GameState, Boolean> trigger;
        private final Runnable action;
    
        Quest(Function<GameState, Boolean> trigger, Runnable action) {
          this.trigger = trigger;
          this.action = action;
        }
    
      }
    
      public static void gameloop(GameState state) {
        // Do all game logic.
    
        for (Quest q : Quest.values())
          if (q.trigger.apply(state))
            q.action.run();
    
      }
    
      public static void trigger500pointHurray() {
        System.out.println("Hurray x500");
      }
    
      public static void trigger5000pointHurray() {
        System.out.println("Hurray x5000");
      }
    
      public static void main(String[] args) {
        gameloop(new GameState());
      }
    }