source: 2014/24/EemeliK/Zombieland/Jypeli/Physics2DDotNet/Ignorers/OneWayPlatformIgnorer.cs @ 5974

Revision 5974, 6.3 KB checked in by empaheik, 4 years ago (diff)
Line 
1#region MIT License
2/*
3 * Copyright (c) 2005-2008 Jonathan Mark Porter. http://physics2d.googlepages.com/
4 *
5 * Permission is hereby granted, free of charge, to any person obtaining a copy
6 * of this software and associated documentation files (the "Software"), to deal
7 * in the Software without restriction, including without limitation the rights to
8 * use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of
9 * the Software, and to permit persons to whom the Software is furnished to do so,
10 * subject to the following conditions:
11 *
12 * The above copyright notice and this permission notice shall be
13 * included in all copies or substantial portions of the Software.
14 *
15 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED,
16 * INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR
17 * PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
18 * LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT,
19 * TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
20 * OTHER DEALINGS IN THE SOFTWARE.
21 */
22#endregion
23
24
25
26#if UseDouble
27using Scalar = System.Double;
28#else
29using Scalar = System.Single;
30#endif
31using System;
32using System.Collections.Generic;
33using AdvanceMath;
34using AdvanceMath.Geometry2D;
35
36
37namespace Physics2DDotNet.Ignorers
38{
39    /// <summary>
40    /// this allows you to have platforms that are one way. like in platform games.
41    /// </summary>
42    public class OneWayPlatformIgnorer : Ignorer
43    {
44        Scalar depthAllowed;
45        Matrix2x2 directionMatrix;
46        public OneWayPlatformIgnorer(Vector2D allowedDirection, Scalar depthAllowed)
47        {
48            Vector2D.Normalize(ref allowedDirection, out allowedDirection);
49            this.depthAllowed = depthAllowed;
50            this.directionMatrix.m00 = allowedDirection.X;
51            this.directionMatrix.m10 = allowedDirection.Y;
52            this.directionMatrix.m01 = -directionMatrix.m10;
53            this.directionMatrix.m11 = directionMatrix.m00;
54        }
55        public override bool BothNeeded
56        {
57            get { return true; }
58        }
59        protected override bool CanCollide(Body thisBody, Body otherBody, Ignorer other)
60        {
61            if (otherBody.IgnoresPhysicsLogics ||
62                otherBody.IsBroadPhaseOnly)
63            {
64                return true;
65            }
66            Matrix2x3 m1, m2;
67            Matrix2x3.Multiply(ref directionMatrix, ref thisBody.Matrices.ToWorld, out m1);
68            Matrix2x3.Multiply(ref directionMatrix, ref otherBody.Matrices.ToWorld, out m2);
69            BoundingRectangle r1, r2;
70            thisBody.Shape.CalcBoundingRectangle(ref m1, out r1);
71            otherBody.Shape.CalcBoundingRectangle(ref m2, out r2);
72            return r1.Min.X + depthAllowed > r2.Max.X;
73        }
74    }
75    /// <summary>
76    /// this allows you to have platforms that are one way. like in platform games.
77    /// </summary>
78    public class GroupedOneWayPlatformIgnorer : Ignorer
79    {
80        class Wrapper
81        {
82            public bool canCollide = false;
83            public int lastUpdate = -2;
84            public Body[] bodies;
85        }
86        Dictionary<Body, Wrapper> wrappers;
87        int lastUpdate;
88        Scalar depthAllowed;
89        Matrix2x2 directionMatrix;
90        public GroupedOneWayPlatformIgnorer(Vector2D allowedDirection, Scalar depthAllowed)
91        {
92            Vector2D.Normalize(ref allowedDirection, out allowedDirection);
93            this.depthAllowed = depthAllowed;
94            this.directionMatrix.m00 = allowedDirection.X;
95            this.directionMatrix.m10 = allowedDirection.Y;
96            this.directionMatrix.m01 = -directionMatrix.m10;
97            this.directionMatrix.m11 = directionMatrix.m00;
98            this.wrappers = new Dictionary<Body, Wrapper>();
99            this.lastUpdate = -1;
100        }
101        public override bool BothNeeded
102        {
103            get { return true; }
104        }
105        protected override bool CanCollide(Body thisBody, Body otherBody, Ignorer other)
106        {
107            if (otherBody.IgnoresPhysicsLogics ||
108                otherBody.IsBroadPhaseOnly)
109            {
110                return true;
111            }
112            Wrapper wrapper;
113            if (wrappers.TryGetValue(otherBody, out wrapper))
114            {
115                if (wrapper.lastUpdate == lastUpdate)
116                {
117                    return wrapper.canCollide;
118                }
119                else
120                {
121                    wrapper.lastUpdate = lastUpdate;
122                    wrapper.canCollide = true;
123                    for (int index = 0; index < wrapper.bodies.Length; ++index)
124                    {
125                        if (!CanCollideInternal(thisBody, wrapper.bodies[index]))
126                        {
127                            wrapper.canCollide = false;
128                            break;
129                        }
130                    }
131                    return wrapper.canCollide;
132                }
133            }
134            else
135            {
136                return CanCollideInternal(thisBody,otherBody);
137            }
138        }
139        private bool CanCollideInternal(Body thisBody, Body otherBody)
140        {
141            Matrix2x3 m1, m2;
142            Matrix2x3.Multiply(ref directionMatrix, ref thisBody.Matrices.ToWorld, out m1);
143            Matrix2x3.Multiply(ref directionMatrix, ref otherBody.Matrices.ToWorld, out m2);
144            BoundingRectangle r1, r2;
145            thisBody.Shape.CalcBoundingRectangle(ref m1, out r1);
146            otherBody.Shape.CalcBoundingRectangle(ref m2, out r2);
147            return (r1.Min.X + depthAllowed > r2.Max.X) ||
148                !(r1.Max.Y > r2.Min.Y &&
149                r1.Min.Y < r2.Max.Y); 
150        }
151        public override void UpdateTime(TimeStep step)
152        {
153            this.lastUpdate = step.UpdateCount;
154            base.UpdateTime(step);
155        }
156        public void AddGroup(Body[] bodies)
157        {
158            Wrapper wrapper = new Wrapper();
159            wrapper.bodies = bodies;
160            for (int index = 0; index < bodies.Length; ++index)
161            {
162                wrappers.Add(bodies[index], wrapper);
163            }
164        }
165    }
166}
Note: See TracBrowser for help on using the repository browser.