source: 2014/24/EemeliK/Zombieland/Jypeli/RoadMap.cs @ 5974

Revision 5974, 6.3 KB checked in by empaheik, 5 years ago (diff)
RevLine 
[5974]1using System;
2using System.Collections.Generic;
3
4namespace Jypeli
5{
6    /// <summary>
7    /// Luo tien. Tie koostuu useasta pienemmästä "pätkästä".
8    /// </summary>
9    public class RoadMap
10    {
11        private Vector[] wayPoints;
12        private Angle[] angles = null;
13
14        /// <summary>
15        /// Tien oletusleveys.
16        /// </summary>
17        public double DefaultWidth { get; set; }
18
19        /// <summary>
20        /// Tien oletuskitka.
21        /// </summary>
22        public double DefaultFriction { get; set; }
23
24        /// <summary>
25        /// Tienpätkät.
26        /// </summary>
27        public GameObject[] Segments { get; private set; }
28
29        /// <summary>
30        /// Funktio, joka luo yksittäisen tienpätkän.
31        /// </summary>
32        /// Funktion tulisi olla muotoa
33        /// <example>
34        /// PhysicsObject CreateSegment( double width, double height, Shape shape )
35        /// </example>
36        /// Funktion tulisi sijoittaa saamansa parametrit uudelle oliolle. Lisäksi
37        /// funktion tarvitsee lisätä luomansa olio peliin.
38        public Func<double, double, Shape, PhysicsObject> CreateSegmentFunction { get; set; }
39
40
41        /// <summary>
42        /// Luo uuden RoadMapin.
43        /// </summary>
44        /// <param name="wayPoints">Lista reittipisteistä.</param>
45        public RoadMap( IList<Vector> wayPoints )
46        {
47            this.DefaultWidth = 10.0;
48            this.DefaultFriction = 1.0;
49            this.CreateSegmentFunction = CreateSegment;
50            this.wayPoints = new Vector[wayPoints.Count];
51            wayPoints.CopyTo( this.wayPoints, 0 );
52            this.Segments = new GameObject[wayPoints.Count - 1];
53        }
54
55        /// <summary>
56        /// Etenemissuunta pisteen kohdalla.
57        /// </summary>
58        /// <param name="wayPointIndex">Pisteen indeksi (alkaen nollasta).</param>
59        public Angle GetAngle( int wayPointIndex )
60        {
61            // TODO: calculate this on the fly so that this check becomes unnecessary.
62            if ( angles == null )
63                throw new Exception( "Call Insert() first" );
64            return angles[wayPointIndex];
65        }
66
67        /// <summary>
68        /// Luo tien kentälle.
69        /// </summary>
70        public void Insert()
71        {
72            if ( wayPoints.Length < 2 )
73            {
74                throw new ArgumentException( "Must have at least 2 points" );
75            }
76
77            angles = new Angle[wayPoints.Length];
78
79            Vector first = wayPoints[0];
80            Vector second = wayPoints[1];
81            Vector toBeginning = ( first - second ).Normalize();
82            Vector beginning = first + toBeginning;
83
84            Vector previousLeft, previousRight;
85            CalculatePoints( beginning, first, second, out previousLeft, out previousRight );
86            angles[0] = ( second - first ).Angle;
87
88            Vector secondToLast = wayPoints[wayPoints.Length - 2];
89            Vector last = wayPoints[wayPoints.Length - 1];
90            Vector toVeryLast = ( last - secondToLast ).Normalize();
91            Vector veryLast = last + toVeryLast;
92             
93            for ( int i = 1; i < wayPoints.Length; i++ )
94            {
95                Vector previous = wayPoints[i - 1];
96                Vector current = wayPoints[i];
97                Vector next;
98
99                Vector toPrevious = ( previous - current ).Normalize();
100                Vector toNext;
101
102                if ( i == wayPoints.Length - 1 )
103                {
104                    next = veryLast;
105                    toNext = toVeryLast;
106                }
107                else
108                {
109                    next = wayPoints[i + 1];
110                    toNext = ( next - current ).Normalize();
111                }
112
113                Vector left, right;
114                CalculatePoints( previous, current, next, out left, out right );
115                angles[i] = ( next - previous ).Angle;
116
117                Vector center = previous + toNext / 2;
118
119                Vector[] vertices = new Vector[4];
120                vertices[0] = previousLeft - center;
121                vertices[1] = previousRight - center;
122                vertices[2] = right - center;
123                vertices[3] = left - center;
124
125                IndexTriangle[] triangles = new IndexTriangle[] 
126                {
127                    new IndexTriangle(0, 3, 1),
128                    new IndexTriangle(1, 3, 2) 
129                };
130
131                ShapeCache cache = new ShapeCache( vertices, triangles );
132                Polygon shape = new Polygon( cache, false );
133
134                PhysicsObject segment = CreateSegmentFunction( 100, 100, shape );
135                segment.Position = center;
136                Segments[i - 1] = segment;
137
138                previousLeft = left;
139                previousRight = right;
140            }
141        }
142
143        private PhysicsObject CreateSegment( double width, double height, Shape shape )
144        {
145            PhysicsObject o = PhysicsObject.CreateStaticObject( width, height, shape );
146            o.Color = Color.Gray;
147            o.IgnoresCollisionResponse = true;
148            o.KineticFriction = DefaultFriction;
149
150            if ( Game.Instance is TopDownPhysicsGame )
151            {
152                TopDownPhysicsGame g = (TopDownPhysicsGame)Game.Instance;
153                g.AddSurface( o );
154            }
155            else
156            {
157                Game.Instance.Add( o );
158            }
159           
160            return o;
161        }
162
163        private void CalculatePoints( Vector previous, Vector current, Vector next, out Vector left, out Vector right )
164        {
165            Vector toNext = ( next - current ).Normalize();
166            Vector toPrevious = ( previous - current ).Normalize();
167            Vector direction = ( next - previous ).Normalize();
168
169            Vector perpendicular = new Vector( direction.Y, -direction.X );
170            Vector toLeft = -perpendicular;
171            Vector toRight = perpendicular;
172
173            left = current + toLeft * DefaultWidth / 2;
174            right = current + toRight * DefaultWidth / 2;
175        }
176
177        public bool IsInside( Vector point )
178        {
179            return ListHelpers.ArrayFind( Segments, seg => seg.IsInside( point ) ) != null;
180        }
181    }
182}
Note: See TracBrowser for help on using the repository browser.