Minecraft源码分析(5) - 饱食度

介绍

介绍饥饿(Hunger)是一个在冒险元素更新中新增的一个游戏机制。在更新之前,玩家食用食物会直接回复生命值。现在,食用则会回复饥饿值,一种随着玩家的不同行动而降低的数值。饥饿条位于屏幕下方玩家的生命值的旁边,表示为10个火腿。当玩家在疾跑时,玩家的饥饿值将会下降的很快。当饥饿值变成6或者更少时,玩家便不能奔跑了。在和平模式下,饥饿值并不会减少,但是其对于玩家生命值的影响并没有消失,并且在游戏中切换难度并不会影响到玩家现有的饥饿值。因此,当你的饥饿值消耗殆尽后,调回和平模式并不会补充它,而且你的生命值将一直持续增加半颗心(和平模式特性)和减半颗心(饥饿)的循环中(这不适用于1.8以后的版本,因为1.8以后和平模式下会自动补饥饿值)。某些特定的食物和药水会有一定几率导致玩家中毒(“饥饿”效果),使玩家的饥饿值下降的更快。腐肉导致中毒的几率有80%,生鸡肉的几率只有30%,河豚则是100%,而食用蜘蛛眼将会直接对玩家生命值造成伤害(“中毒”效果)。


Minecraft源码分析(5) - 饱食度_第1张图片


代码分析

相关设计类模型如下

Minecraft源码分析(5) - 饱食度_第2张图片


实际上所谓的饱食度其实分为三个部分: 食物水平(foodLevel),取值范围是从0到20,它表示的是玩家饥饿值。1点等于(半个“火腿”)。 食物饱和度(foodSaturationLevel)这是一项隐藏的食物变量,一种在消耗食物水平之前先消耗的值。食用任何食物都会添加一点这种变量。注意这个变量是无法超过食物水平的。当这个变量到达0时,饥饿条会颤抖一下。 食物计刻表(foodTimer)当食物水平大于17或者等于0时,它就会以刻(1/20秒)为单位来增加。当其到达80时,就会重设至0,并且对玩家生命值治疗或者伤害一点(半颗心)。 饥饿等级(foodExhuastionLevel),取值范围是从0.0到4.0,玩家的每项行动都会增加它。当饥饿等级到达4.0时,它会自动减4.0,并且从食物饱和度或者食物水平(当食物饱和度等于0时)减去1点。


食物有两个主要属性

 foodLevel : 吃掉它可以恢复的食物水平;

 saturationModifier:是该食物可以恢复的foodSaturationLevel系数。

 吃掉食物对FoodStates的改变的接口如下

public void AddStats(float foodLevelIn, float foodSaturationModifier)
    {
        this.foodLevel = Mathf.Min(foodLevelIn + this.foodLevel, maxFoodLevel);
        this.foodSaturationLevel = Mathf.Min(this.foodSaturationLevel + (float)foodLevelIn * foodSaturationModifier * 2.0F, (float)this.foodLevel);
    }



FoodStates的OnUpdate函数是放在Tick里面执行的。


public void OnUpdate(EntityPlayer player)
    {

        // when foodExhaustionLevel > 4 , minus foodSaturationLevel or food level.
        if (this.foodExhaustionLevel > 4.0F)
        {
            this.foodExhaustionLevel -= 4.0F;

            if (this.foodSaturationLevel > 0.0F)
            {
                this.foodSaturationLevel = Mathf.Max(this.foodSaturationLevel - 1.0F, 0.0F);
            }
            else
            {
                this.foodLevel = Mathf.Max(this.foodLevel - 1, 0);
            }
        }

        //Heal player when food level >= 18
        if (this.foodLevel >= 0.9f * maxFoodLevel && player.ShouldHeal())
        {
            ++this.foodTimer;

            if (this.foodTimer >= 80)
            {
                player.Health = player.Health + 0.1f * player.MaxHealth;
                this.AddExhaustion(3.0F);
                this.foodTimer = 0;
            }
        }
        //Damage player when food level <= 0
        else if (this.foodLevel <= 0)
        {
            ++this.foodTimer;

            if (this.foodTimer >= 80)
            {
                player.AttackEntityFrom(DamageSource.starve, 0.1f * player.MaxHealth);
                this.foodTimer = 0;
            }
        }
        else
        {
            this.foodTimer = 0;
        }
    }


逻辑如下
1. 玩家的各种行为都会造成foodExhaustionLevel 的增加,比如跳跃一次会增加0.2,挖一下块会增加0.3等等,当foodExhaustionLevel大于4的时候,会造一点消耗,如果此时foodSaturationLevel 大于0,就消耗一点foodSaturationLevel,否则就直接消耗foodLevel。
2. 当foodLevel 大于0.9 * maxFoodLevel的时候,且玩家的可以回血(血量不为满,没有受到不能加血的buff),玩家开始以 0.1*最大血量/4s 的速度开始回血,每回一次血会增加3的foodExhaustionLevel。
3. 当foodLevel小于0的时候,玩家开始以0.1*最大血量/4s 的速度开始掉血。

参考

Minecraft wiki 食物 - http://minecraft.gamepedia.com/Food

Minecraft wiki 饥饿 - http://minecraft-zh.gamepedia.com/%E9%A5%A5%E9%A5%BF










你可能感兴趣的:(Minecraft源码分析(5) - 饱食度)