2016-09-24 55 views
-1

我正在用C++创建一个游戏。在这个游戏中,我创建了一个名为Player的类。 Player类具有一个称为magic的属性。这个属性是一个整数,在整个游戏中不断增加,当用户做某事或完成一项任务时,他们可以获得magic。一旦达到某个点,用户就会获得一个新的咒语,这些咒语在玩家类中被保存在一个阵列中。如何等待某个变量达到某个数字才能执行某些操作?

我希望能够在整个游戏中检查这个属性,看它是否达到了一定的水平。

我以为每次magic属性都会检查一次,但是这会在每次添加很多条件时出现。如:

user.magic++ 
if(user.magic == 2) { 
    //Give a new spell 
} 
else if(user.magic == 3) { 
    //Give a new spell 
} 

而做到这一点的magic属性被更新每次。这似乎需要花费大量的时间和精力来不断输入。我应该把上面的代码放在一个函数中,并且每次更新magic时都运行它?

有没有更好的方法来做到这一点?

+0

其他语言/环境尤其是图形用户界面使用“可观察”对象(例如Javascript + DOM中的addEventListener),其中添加了一个回调函数,当变量发生变化时被调用 –

+0

我没有看到任何问题以您的方式执行想要做到这一点。这对我来说确实很好 – Merlin

+0

@Lorenzo想想如果'user'已经获得魔术师会发生什么,并且该功能被多次调用。 – user4581301

回答

2

第一步:将user.magic从可用的法术中分离出来。原因:也许将来你也想为NPC-es分配法术,而不仅仅是用户。

struct spell { 
    int type; 
    int cost; 
    int damage; 
} 

static const spell walk_on_water={SURVIVAL, 10, 0}; 
static const spell resurect={DARK_MAGIC, 100, 0}; 
static const spell fireball_minor={OFFENSIVE, 30, 4}; 
static const spell fireball_big={OFFENSIVE, 300, 25}; 

void getSpellsForMagicLevel(int userMagic, std::vector<const spell&>& resultHere) { 
    resultHere.clear(); 
    switch(useMagic) { 
    case 1: 
     resultHere.push_back(walk_on_water); 
     break; 
    case 2: 
     resultHere.push_back(walk_on_water); 
     resultHere.push_back(fireball_minor); 
     break; 
    //... 
    case 10: 
     resultHere.push_back(walk_on_water); 
     resultHere.push_back(resurect); 
     resultHere.push_back(fireball_minor); 
     resultHere.push_back(fireball_big); 
     break; 
    } 
} 

然后调用这个单一的功能,你想知道什么可用的法术的存在是有player.magic


然后你注意到用户的咒语库存仅改变magic修改时(达到任何时间 - 由于增加了经验 - 或者由于例如由于破坏性药水导致) - 那么为什么依靠一次又一次地调用这个函数呢?所以:

class Player { 
protected: 
    int magic; 
    std::vector<const spell&> spell_inventory; 

// ... 
    void set_magic_level(int newMagicLevel) { 
    if(this->magic != newMagicLevel) { // do nothing if no change 
     this->magic = newMagicLevel; 
     getSpellsForMagicLevel(this->magic, this->spell_inventory); 
    } 
    } 
// ... 
public: 
// ... 
    int get_magic_level() const { 
    return this->magic; 
    } 
}; 

class User : public Player { 
    //... 
public: 

    void newExperience(const Event& somethingThatHappened) 
    { 
    switch(somethingThatHappened.type) { 
    case EXPERIENCE_THRESHOLD_REACHED: 
     this->set_magic_level(this->get_magic_level()+1); 
     break; 
    case DUMBING_POTION: 
     this->set_magic_level(
      this->get_magic_level()-somethingThatHappened.get_damage() 
     ); 
     break; 
    // etc... 
    } 
    } 
}; 

class NonPlayerCharacter : public Player { 
    //... 
public: 
    // NPC-es don't evolve, they are just spawned 
    // So no newExperience method for them. 
}; 
+0

(人们只能希望downvoter有勇气解释) –

+0

也许是因为你的回答是一种“矫枉过正”。它不直接回答OP的问题。我赞成你,因为你的答案的质量和它表现出很好地利用封装(OP应该尽快学会)。人们似乎以任何理由downvote ... – Cedric

+0

@Cedric“封装的一个很好的使用(OP应该尽快学会)”。我的矫枉过正的目的 - 教他们钓鱼(而不是让他们火焰:) :) –

1

如何使用地图?所以你可以使用解锁某些法术(又名int)作为钥匙所需的法力值数量,并存储用于解锁法术的字符串或其他工具,并授予玩家这种法术。我的意思是,从技术上来说,它比拥有大量硬编码循环更好,在此实现中,您可以更改地图并使用相同的函数。

编辑以另一种方式来设计这个,你给玩家所有从一开始的法术,但通过限制它“只能施放某种法术时,比赛MAGIC要求”,你仍然可以使用地图作为一个方便的工具

+0

有趣的想法!我会试试这个。 –

+0

我的意思是,你甚至可以使用另一种方法从文件中读取信息并将法术信息存储到地图中,这样更容易更新游戏数据,因为它们几乎都是从配置文件加载的。 – BrokenCodex

0

可以随时增加“持续”值(每次发出特定命令时都带有一个定时器?)是可能的,但是那么增加一个新咒语的步骤太小了。这意味着每一个动作你都会得到一个新的咒语!

取而代之,请使用如下所示:将experience的值设置为0。然后,在你的主循环中(同一个定时器,或者你正在使用的任何东西),增加这个值。如果它达到一些合理的数值,比如100,则添加一个新的拼写并将experience的值重新设置为0

+0

我会编辑我的问题更清楚,获得魔法,你必须完成任务,某些任务会给你一个新的魔法配额,它不在计时器上。 –

+0

@爱丽丝:无论变量何时增加,思路都是一样的。你最多测试一次'经验',如果达到,则添加一个咒语;然后重置该值,以便可以触发下一个事件。 – usr2564301

5

充分利用.magic成员变量private,这样来增加魔法的唯一方法是调用一个方法如user.IncrementMagic(),而不是被允许直接说user.magic++。随后,该方法的实现可能看起来像:

Player::IncrementMagic() 
{ 
    magic++; 
    CheckUpdatedMagicLevel(); 
} 
Player::CheckUpdatedMagicLevel() 
{ 
    if(magic == 2) 
    { 
     // etc 
    } 
    // etc 
} 

如果需要的话,你也可以写在不同的方式,e.g操纵magic另外的方法。 DecrementMagicSetNewMagicLevel(x)。这些方法也会在内部调用CheckUpdatedMagicLevel()

相关问题