Inheritance: TimeableObject
Exemplo n.º 1
0
        /// <summary>
        /// Return the next value of the effector.
        /// </summary>
        /// <param name="obj"></param>
        /// <returns></returns>
        protected virtual T2 GetNext(EffectableObject obj)
        {
            var next = Func(ElapsedTime, ElapsedFrames);

            if (Prev != null)
            {
                // Combined is just the value after performing the operation O(x, y)
                // where x is the previous value and y is the next value.
                var combined = Op.Operate(Prev, next);

                if (ValueType == EffectorValueType.RelativeToStart)
                {
                    var init = InitialValues[obj];

                    #region Explanation of why we must check if the effector is InPlace and RelativeToStart.

                    // Alright here's the breakdown. The following table outlines the
                    // general term for a given ValueType and OperatorType, where x0 is
                    // the initial value, F is Func, and tn and fn are the time and frame
                    // counts at the nth call to UpdateEffector respectively:
                    //
                    // ______________________________________________________________
                    // |                |     RelativeToStart    |     Absolute     |
                    // |------------------------------------------------------------|
                    // | InPlace:       |     xn = F(tn, fn)     |   = F(tn, fn)    |
                    // |----------------|------------------------|------------------|
                    // | Additive:      |  xn = x0 + Σ F(tn, fn) |   = Σ F(tn, fn)  |
                    // |----------------|------------------------|------------------|
                    // | Multiplicative |  xn = x0 * Π F(tn, fn) |   = Π F(tn, fn)  |
                    // --------------------------------------------------------------
                    //
                    // Notice how for Inplace and RelativeToStart, the general term is
                    // F(tn, fn). Although this is technically correct and makes sense with
                    // respect to the rest of the values (xn = O(x(n - 1), F(tn, fn)) in general,
                    // where O is the operation, so for InPlace O(x, y) = y means xn = F(tn, fn)),
                    // it feels unnatural or unintuitive.
                    //
                    // Intuitively, it makes more sense that InPlace and RelativeToStart would mean
                    // the general term would be x0 + F(tn, fn), since that is really what "Relative
                    // To Start" means.
                    //
                    // Mechanically, it also makes sense that you would want InPlace and RelativeToStart
                    // to do something different from InPlace and Absolute. For example, if F(tn, fn) = tn,
                    // and x0 = 3, then you would expect the general term to be 3 + tn, not just tn.
                    // If InPlace and RelativeToStart didn't do that, then there would be no way of
                    // achieving the desired outcome (Additive and RelativeToStart would give 3 + Σ tn).
                    //
                    // Thus, if the effector is both InPlace and RelativeToStart, then the general
                    // term is actually xn = x0 + F(tn, fn), instead of the term predicted by the pattern
                    // xn = O(x(n - 1), F(tn, fn)).

                    #endregion

                    return(inPlace_and_relativeToStart ? Combine_InPlaceAndRelativeToStart(init, combined)
                                                       : Op.Operate(init, combined));
                }
                return(combined);
            }
            return(next);
        }
Exemplo n.º 2
0
        protected override void AssignNextValue(EffectableObject obj, float nextVal)
        {
            var prevVec = obj.Get <Vector2>(EffectedPropertyName);

            prevVec.X = nextVal;
            obj.Set(EffectedPropertyName, prevVec);
        }
Exemplo n.º 3
0
        public void UpdateEffector(EffectableObject obj)
        {
            if (!Reusable)
            {
                obj = Object;
            }

            var next = GetNext(obj);

            Prev = next;

            AssignNextValue(obj, next);
        }
Exemplo n.º 4
0
        public virtual void InternalInitialize(EffectableObject obj)
        {
            if (Initialized)
            {
                string exceptionMessage = "The most likely cause for this is the same effector " +
                                          "was added to multiple objects. Check to ensure you aren't reusing the same " +
                                          "effector instance.";
                if (Anonymous)
                {
                    exceptionMessage = String.Format(
                        "Anonymous effector of type '{0}' was initialized twice.", this.GetType()) +
                                       exceptionMessage;
                }
                else
                {
                    exceptionMessage = String.Format(
                        "Effector with name '{0}' and type '{1}' was initialized twice.",
                        EffectorName, this.GetType()) +
                                       exceptionMessage;
                }
                throw new EffectorException(exceptionMessage);
            }

            if (ValueType == EffectorValueType.RelativeToStart)
            {
                InitialValues.Add(obj, CoerceTo((T1)obj.Get(EffectedPropertyName)));
            }

            // If this effector is reusable, then it may be used for multiple
            // ArtemisObject instances, meaning we can't store an internal reference
            // to any single one.
            //
            // The advantage of using a non-reusable effector over a reusable one is
            // that the effector can initialize it's own properties based on it's
            // assigned instance.
            if (!Reusable)
            {
                Object = obj;
            }

            Initialize();

            Initialized = true;
        }
Exemplo n.º 5
0
 protected abstract void AssignNextValue(EffectableObject obj, T2 t2);
Exemplo n.º 6
0
 protected override void AssignNextValue(EffectableObject obj, T val)
 {
     obj.Set(EffectedPropertyName, val);
 }