Saturday, February 18, 2012

Very Basic Influence Map

So I finally had a little time and was able to edit the control scheme of the maze generation game so that I could control it with a xbox360 controller. I was also able to create a very basic influence map class which I hope to improve upon.

There are numerous uses for influence maps but for this demo, our influence map helps my monster Santa explore. Previously, the monster simply takes a random value and could get stuck in a loop for awhile before the random number generator picks a lucky value and stops the monster from moving in a circle. With influence map, I assign each grid location a numeric value from 0 to 100 with 100 being the most influential value. As the monster reaches a grid location, I set that location's influence value to the maximum. Over time, the value of this grid will slowly decrease until it reaches 0. This makes the AI more believable and gives the effect of "Oh I haven't been to grid x for a long time so I'm not sure what's really there". The second part is to decide what to do with these values. For my monster, as it explores, I've given it a visibility range of 1 which means it will only look at the adjacent grid locations. From those grid locations, it will look at each of its influence value and will move towards the lowest value possible. Because this is done in the monster's explore state, the above implementation creates the behavior of the monster identifying where it hasn't checked in awhile a proceeds to that location.

 
//simply a 2d grid structure with values that decay over time
    class InfluenceMap
    {
        public const float decayInterval = 5.0f;    //decreases influence value every this amount of seconds
        public const float decayAmount = 0.25f;     //for every decayInterval, decrease influence value by this much
        public readonly float maxValue = 100.0f;    //the maximum value a influence location can have

        /// 
        /// 
        /// 
        /// the maximum number of rows        /// the maximum number of columns        public InfluenceMap(uint row, uint col)
        {
            _gridPositions = new float[row, col];
            for (uint i = 0; i < _maxRow; ++i)
            {
                for (uint j = 0; j < _maxCol; ++j)
                {
                    _gridPositions[i, j] = 0.0f;
                }
            }

            _currentInterval = 0.0f;
            _maxRow = row;
            _maxCol = col;
        }

        public void SetLocation(uint row, uint col)
        {
            _gridPositions[row, col] = maxValue;
        }

        public float GetValue(int row, int col)
        {
            return _gridPositions[row, col];
        }

        public void Update(float dt)
        {
            _currentInterval += dt;
            if (_currentInterval > decayInterval)
            {
                ApplyDecay();
                _currentInterval = 0.0f;
            }
        }

        private void ApplyDecay()
        {
            for (uint i = 0; i < _maxRow; ++i)
            {
                for (uint j = 0; j < _maxCol; ++j)
                {
                    _gridPositions[i, j] = MathHelper.Clamp(_gridPositions[i, j] - decayAmount, 0.0f, maxValue);
                }
            }
        }

        private float[,] _gridPositions;
        private float _currentInterval;
        private uint _maxRow;
        private uint _maxCol;
    }
Here is a video showing the maze generation as well as the new basic influence map implementation on the monster.
It's now slightly smarter in its decision in terms of picking which route to take. Something I can improve on is increasing the visibility range of the monster so it looks up to 5 grid location ahead for example. I can also improve on the influence map by performing a propagation effect so that when an influence value is set or we perform decay on the grids, each grid will take into account their neighbors as well which will create a much smoother and more realistic mapping.

No comments:

Post a Comment