source: 2013/30/MiskaK/MW2(My Warfare 2)/Paranneltu Jypeli/GameObjects/GameObject/Oscillator.cs @ 4507

Revision 4507, 5.5 KB checked in by anlakane, 6 years ago (diff)

Talletus.

Line 
1using System;
2using System.Collections.Generic;
3using System.Linq;
4using System.Text;
5
6namespace Jypeli.GameObjects
7{
8    /// <summary>
9    /// Harmoninen värähtelijä.
10    /// </summary>
11    internal abstract class Oscillator : Updatable, Destroyable
12    {
13        protected double t = 0;
14
15        public IGameObject Object;
16        public double Frequency;
17        public double Phase;
18        public double Damping;
19
20        public bool IsUpdated { get { return true; } }
21        public bool IsDestroyed { get; private set; }
22
23        public event Action Destroyed;
24
25        public Oscillator( IGameObject obj, double f, double phase, double damping )
26        {
27            this.Object = obj;
28            this.Frequency = f;
29            this.Phase = phase;
30            this.Damping = damping;
31        }
32
33        public double GetDampingMultiplier()
34        {
35            return Math.Pow( Math.E, -Damping * t );
36        }
37
38        public void Update( Time time )
39        {
40            t += time.SinceLastUpdate.TotalSeconds;
41
42            if ( GetDampingMultiplier() < 1e-12 )
43            {
44                Stop();
45                Destroy();
46            }
47
48            Apply();
49        }
50
51        protected abstract void Apply();
52
53        public void Destroy()
54        {
55            IsDestroyed = true;
56            if ( Destroyed != null ) Destroyed();
57        }
58
59        public abstract void Stop();
60    }
61
62    /// <summary>
63    /// Harmoninen värähtelijä akselin suhteen.
64    /// </summary>
65    internal class LinearOscillator : Oscillator
66    {
67        public Vector Center;
68        public Vector Axis;
69        public double Amplitude;
70
71        public LinearOscillator( IGameObject obj, Vector axis, double a, double f, double phase, double damping )
72            : base( obj, f, phase, damping )
73        {
74            this.Axis = axis.Normalize();
75            this.Amplitude = a;
76            this.Center = obj.Position - Axis * Amplitude * Math.Sin( phase );
77
78            if ( Object is PhysicsObject )
79            {
80                ( (PhysicsObject)obj ).Velocity = Axis * Amplitude * 2 * Math.PI * f * Math.Cos( phase );
81            }
82        }
83
84        public Vector GetOffset()
85        {
86            return Axis * Amplitude * GetDampingMultiplier() * Math.Sin( 2 * Math.PI * Frequency * t + Phase );
87        }
88
89        bool IsDynamic( IGameObject obj )
90        {
91            return obj is PhysicsObject && !double.IsInfinity( ( (PhysicsObject)obj ).Mass );
92        }
93
94        protected override void Apply()
95        {
96            if ( IsDynamic( Object ) )
97            {
98                PhysicsObject physObj = (PhysicsObject)Object;
99                double d = ( Object.Position - Center ).ScalarProjection( Axis );
100                double angularFreq = 2 * Math.PI * Frequency;
101                double k = Math.Pow( angularFreq, 2 ) * physObj.Mass;
102                double force = -k * d;
103                double dampingForce = physObj.Velocity.ScalarProjection( Axis ) * Damping * physObj.Mass;
104                double totalForce = force - dampingForce;
105
106                physObj.Push( totalForce * Axis );
107            }
108            else
109            {
110                Object.Position = Center + GetOffset();
111            }
112        }
113
114        public override void Stop()
115        {
116            if ( Object is PhysicsObject )
117            {
118                ( (PhysicsObject)Object ).StopAxial( Axis );
119            }
120        }
121    }
122
123    /// <summary>
124    /// Harmoninen värähtelijä pyörintäliikkeelle.
125    /// </summary>
126    internal class AngularOscillator : Oscillator
127    {
128        public double Direction;
129        public Angle Center;
130        public UnlimitedAngle Amplitude;
131
132        public AngularOscillator( IGameObject obj, double dir, UnlimitedAngle a, double f, double damping )
133            : base( obj, f, 0, damping )
134        {
135            this.Direction = Math.Sign( dir );
136            this.Amplitude = a;
137            this.Center = obj.Angle;
138
139            if ( Object is PhysicsObject )
140            {
141                ( (PhysicsObject)obj ).AngularVelocity = Direction * 2 * Amplitude.Radians * f;
142            }
143        }
144
145        public UnlimitedAngle GetOffset()
146        {
147            return Direction * Amplitude * GetDampingMultiplier() * Math.Sin( 2 * Math.PI * Frequency * t + Phase );
148        }
149
150        bool IsDynamic( IGameObject obj )
151        {
152            return obj is PhysicsObject && !double.IsInfinity( ( (PhysicsObject)obj ).MomentOfInertia );
153        }
154
155        protected override void Apply()
156        {
157            if ( IsDynamic( Object ) )
158            {
159                PhysicsObject physObj = (PhysicsObject)Object;
160                double d = Math.PI * ( Object.Angle.Radians - Center.Radians );
161                double k = Math.Pow( Frequency, 2 ) * physObj.MomentOfInertia;
162                double torque = -k * d;
163                double dampingTorque = physObj.AngularVelocity * Damping * physObj.MomentOfInertia;
164                double totalTorque = torque - dampingTorque;
165
166                physObj.ApplyTorque( totalTorque );
167            }
168            else
169            {
170                Object.Angle = Angle.Sum( Center, GetOffset() );
171            }
172        }
173
174        public override void Stop()
175        {
176            if ( Object is PhysicsObject )
177            {
178                ( (PhysicsObject)Object ).StopAngular();
179            }
180        }
181    }
182}
Note: See TracBrowser for help on using the repository browser.