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

Revision 5974, 6.3 KB checked in by empaheik, 5 years ago (diff) |
---|

Rev | Line | |
---|---|---|

[5974] | 1 | using System; |

2 | using System.Collections.Generic; | |

3 | ||

4 | namespace 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.