source: 2014/24/EemeliK/Zombieland/Jypeli/GameObjects/PhysicsObject/Dimensions.cs @ 5974

Revision 5974, 6.8 KB checked in by empaheik, 4 years ago (diff)
Line 
1#region MIT License
2/*
3 * Copyright (c) 2009 University of Jyväskylä, Department of Mathematical
4 * Information Technology.
5 *
6 * Permission is hereby granted, free of charge, to any person obtaining a copy
7 * of this software and associated documentation files (the "Software"), to deal
8 * in the Software without restriction, including without limitation the rights
9 * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
10 * copies of the Software, and to permit persons to whom the Software is
11 * furnished to do so, subject to the following conditions:
12 *
13 * The above copyright notice and this permission notice shall be included in
14 * all copies or substantial portions of the Software.
15 *
16 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
17 * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
18 * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
19 * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
20 * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
21 * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
22 * THE SOFTWARE.
23 */
24#endregion
25
26/*
27 * Authors: Tero Jäntti, Tomi Karppinen, Janne Nikkanen.
28 */
29
30using System;
31using Physics2DDotNet.Shapes;
32using AdvanceMath;
33using Physics2DDotNet;
34using System.Diagnostics;
35namespace Jypeli
36{
37    public partial class PhysicsObject
38    {
39        /// <summary>
40        /// Fysiikkamoottorin käyttämä tietorakenne.
41        /// </summary>
42        public Body Body { get; private set; }
43
44        /// <summary>
45        /// Olion paikka koordinaatistossa. Käsittää sekä X- että Y-koordinaatin.
46        /// </summary>
47        [Save]
48        public override Vector Position
49        {
50            get
51            {
52                Vector2D v = Body.State.Position.Linear;
53                return new Vector( v.X, v.Y );
54            }
55            set { Body.State.Position.Linear = new Vector2D( value.X, value.Y ); }
56        }
57
58        /// <summary>
59        /// Olion koko (x on leveys, y on korkeus).
60        /// </summary>
61        [Save]
62        public override Vector Size
63        {
64            get
65            {
66                return base.Size;
67            }
68            set
69            {
70                Body.Shape = CreatePhysicsShape( base.Shape, value );
71                base.Size = value;
72            }
73        }
74
75        /// <summary>
76        /// Kulma, jossa olio on. Oliota voi pyörittää kulmaa vaihtamalla.
77        /// </summary>
78        [Save]
79        public override Angle Angle
80        {
81            get { return Angle.FromRadians( Body.State.Position.Angular ); }
82            set { Body.State.Position.Angular = value.Radians; }
83        }
84
85        /// <summary>
86        /// Olion muoto.
87        /// </summary>
88        public override Shape Shape
89        {
90            get { return base.Shape; }
91            set
92            {
93                SetShape( value, GetDefaultParameters( Width, Height ) );
94            }
95        }
96
97        internal void SetShape( Shape shape, CollisionShapeParameters parameters )
98        {
99            base.Shape = shape;
100            Body.Shape = CreatePhysicsShape( shape, Size, parameters );
101        }
102
103        internal static IShape CreatePhysicsShape( Shape shape, Vector size )
104        {
105            return CreatePhysicsShape( shape, size, GetDefaultParameters( size.X, size.Y ) );
106        }
107
108        /// <summary>
109        /// Creates a shape to be used in the Physics Body. A physics shape is scaled to the
110        /// size of the object. In addition, it has more vertices and some additional info
111        /// that is used in collision detection.
112        /// </summary>
113        internal static IShape CreatePhysicsShape( Shape shape, Vector size, CollisionShapeParameters parameters )
114        {
115            if ( shape is RaySegment )
116            {
117                RaySegment raySegment = (RaySegment)shape;
118                Physics2DDotNet.Shapes.RaySegment singleSegment = new Physics2DDotNet.Shapes.RaySegment(
119                    new Vector2D( raySegment.Origin.X, raySegment.Origin.Y ),
120                    new Vector2D( raySegment.Direction.X, raySegment.Direction.Y ),
121                    raySegment.Length );
122                return new RaySegmentsShape( singleSegment );
123            }
124            else if ( shape is Ellipse )
125            {
126                Debug.Assert( shape.IsUnitSize );
127
128                double smaller = Math.Min( size.X, size.Y );
129                double bigger = Math.Max( size.X, size.Y );
130                // Average between width and height.
131                double r = smaller / 2 + ( bigger - smaller ) / 2;
132                int vertexCount = (int)Math.Ceiling( ( 2 * Math.PI * r ) / parameters.MaxVertexDistance );
133
134                if ( Math.Abs( size.X - size.Y ) <= double.Epsilon )
135                {
136                    // We get more accurate results by using the circleshape.
137                    // in addition, the circleshape does not need a DistanceGrid
138                    // object (which is slow to initialize) because calculations
139                    // for a circleshape are much simpler.
140                    return new CircleShape( r, vertexCount );
141                }
142                else
143                {
144                    Vector2D[] vertexes = new Vector2D[vertexCount];
145
146                    double a = 0.5 * size.X;
147                    double b = 0.5 * size.Y;
148
149                    for ( int i = 0; i < vertexCount; i++ )
150                    {
151                        double t = ( i * 2 * Math.PI ) / vertexCount;
152                        double x = a * Math.Cos( t );
153                        double y = b * Math.Sin( t );
154                        vertexes[i] = new Vector2D( x, y );
155                    }
156
157                    return new PolygonShape( vertexes, parameters.DistanceGridSpacing );
158                }
159            }
160            else
161            {
162                Vector2D[] originalVertexes = new Vector2D[shape.Cache.OutlineVertices.Length];
163                for ( int i = 0; i < shape.Cache.OutlineVertices.Length; i++ )
164                {
165                    Vector v = shape.Cache.OutlineVertices[i];
166                    if ( shape.IsUnitSize )
167                    {
168                        v.X *= size.X;
169                        v.Y *= size.Y;
170                    }
171                    originalVertexes[i] = new Vector2D( v.X, v.Y );
172                }
173
174                Vector2D[] polyVertexes = VertexHelper.Subdivide( originalVertexes, parameters.MaxVertexDistance );
175
176                return new PolygonShape( polyVertexes, parameters.DistanceGridSpacing );
177            }
178        }
179    }
180}
Note: See TracBrowser for help on using the repository browser.