source: 2014/24/EemeliK/Zombieland/Jypeli/Physics2DDotNet/PhysicsLogics/RaySegmentsCollisionLogic.cs @ 10336

Revision 5974, 5.8 KB checked in by empaheik, 5 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#if UseDouble
26using Scalar = System.Double;
27#else
28using Scalar = System.Single;
29#endif
30using System;
31using System.Collections.Generic;
32using System.Collections.ObjectModel;
33
34using AdvanceMath;
35
36using AdvanceMath.Geometry2D;
37using Physics2DDotNet.Shapes;
38
39namespace Physics2DDotNet.PhysicsLogics
40{
41
42    public sealed class RaySegmentsCollisionInfo
43    {
44        internal Body body;
45        internal Scalar distance = -1;
46
47        public Body Body
48        {
49            get { return body; }
50        }
51
52        public Scalar Distance
53        {
54            get { return distance; }
55        }
56    }
57    /// <summary>
58    /// A class to manage a RaySegmentsShape collisions
59    /// </summary>
60    public sealed class RaySegmentsCollisionLogic : PhysicsLogic
61    {
62        static void Reset(RaySegmentsCollisionInfo[] info)
63        {
64            for (int index = 0; index < info.Length; ++index)
65            {
66                info[index].distance = -1;
67                info[index].body = null;
68            }
69        }
70        static void Init(RaySegmentsCollisionInfo[] info)
71        {
72            for (int index = 0; index < info.Length; ++index)
73            {
74                info[index] = new RaySegmentsCollisionInfo();
75            }
76        }
77
78        public event EventHandler NewInfo;
79
80        Body body;
81        RaySegmentsCollisionInfo[] current;
82        RaySegmentsCollisionInfo[] next;
83
84
85        public RaySegmentsCollisionLogic(Body body)
86            : base(GetLifeTime(body))
87        {
88            this.body = body;
89            RaySegmentsShape shape = body.Shape as RaySegmentsShape;
90            if (shape == null) { throw new ArgumentException("the shape must be a RaySegmentsShape"); }
91            SetShape(shape);
92            body.LifetimeChanged += OnLifetimeChanged;
93            body.ShapeChanged += OnShapeChanged;
94            body.Collided += OnCollided;
95        }
96        public ReadOnlyCollection<RaySegmentsCollisionInfo> Collisions
97        {
98            get
99            {
100                return new ReadOnlyCollection<RaySegmentsCollisionInfo>(current);
101            }
102        }
103
104
105        void SetShape(RaySegmentsShape shape)
106        {
107            current = new RaySegmentsCollisionInfo[shape.Segments.Length];
108            next = new RaySegmentsCollisionInfo[shape.Segments.Length];
109            Init(current);
110            Init(next);
111        }
112
113        void OnCollided(object sender, CollisionEventArgs e)
114        {
115            if (e.Other.IgnoresPhysicsLogics) { return; }
116            RaySegmentIntersectionInfo info = e.CustomCollisionInfo as RaySegmentIntersectionInfo;
117            if (info != null)
118            {
119                ReadOnlyCollection<Scalar> distances = info.Distances;
120
121                for (int index = 0; index < next.Length; ++index)
122                {
123                    RaySegmentsCollisionInfo cinfo = next[index];
124                    if (distances[index] != -1 && (cinfo.distance == -1 || distances[index] < cinfo.distance))
125                    {
126                        cinfo.body = e.Other;
127                        cinfo.distance = distances[index];
128                    }
129                }
130            }
131        }
132
133        void OnShapeChanged(object sender, EventArgs e)
134        {
135            RaySegmentsShape newShape = body.Shape as RaySegmentsShape;
136            if (newShape == null)
137            {
138                this.Lifetime = new Lifespan();
139                this.Lifetime.IsExpired = true;
140                ClearEvents();
141            }
142            else
143            {
144                SetShape(newShape);
145            }
146        }
147        void ClearEvents()
148        {
149            body.LifetimeChanged -= OnLifetimeChanged;
150            body.ShapeChanged -= OnShapeChanged;
151            body.Collided -= OnCollided;
152        }
153        void OnLifetimeChanged(object sender, EventArgs e)
154        {
155            this.Lifetime = body.Lifetime;
156        }
157        protected internal override void BeforeAddCheck(PhysicsEngine engine)
158        {
159            if (body.Engine != engine)
160            {
161                throw new InvalidOperationException("Body must be in the engine");
162            }
163            base.BeforeAddCheck(engine);
164        }
165        protected internal override void RunLogic(TimeStep step)
166        {
167            RaySegmentsCollisionInfo[] temp = current;
168            current = next;
169            next = temp;
170            Reset(next);
171            if (NewInfo != null)
172            {
173                NewInfo(this, EventArgs.Empty);
174            }
175        }
176    }
177
178}
Note: See TracBrowser for help on using the repository browser.