Jypeli  9
The simple game programming library
Surface.cs
Siirry tämän tiedoston dokumentaatioon.
1 using System;
2 
3 namespace Jypeli
4 {
8  public class Surface : PhysicsObject
9  {
10  double[] heights = null;
11  double scale = 1.0;
12 
13  #region Constructors
14 
28  public Surface( double width, double[] heights, double scale )
29  : base( width, CalculateHeight( heights, scale ), CreateRuggedShape( width, heights, scale ) )
30  {
32  }
33 
39  public Surface( double width, double height )
40  : base( width, height, Shape.Rectangle )
41  {
42  InitializeFlat( height );
43  }
44 
45  private void InitializeFlat( double height )
46  {
47  this.heights = new double[1] { height };
48  this.scale = 1.0;
49 
50  this.Color = Color.ForestGreen;
51  this.TextureFillsShape = true;
52  MakeStatic();
53  }
54 
55  private void InitializeRugged( double[] heights, double scale )
56  {
57  this.heights = heights;
58  this.scale = scale;
59  this.Color = Color.ForestGreen;
60  this.TextureFillsShape = true;
61  MakeStatic();
62  }
63 
72  public Surface( double width, double min, double max, int points )
73  : this( width, RandomGen.NextDoubleArray( Math.Max( min, 1.0f ), max, points ), 1.0 )
74  {
75  }
76 
86  public Surface( double width, double min, double max, int points, int maxchange )
87  : this( width, RandomGen.NextDoubleArray( Math.Max( min, 1.0f ), max, points, maxchange ), 1.0 )
88  {
89  }
90 
91  #endregion
92 
93  #region Static private methods for constructors
94 
95  private static double CalculateHeight( double[] heights, double scale )
96  {
97  if ( heights.Length < 2 )
98  throw new Exception( "At least two Y-points needed in order to create ground" );
99  if ( heights.Min() < 1 )
100  throw new Exception( "The heights must be positive and at least 1" ); // JN: doesn't work well with 0 values (slow and memory usage problems)
101 
102  return heights.Max() * scale;
103  }
104 
105  private static Vector[] CalculateVertexes( double width, double[] heights, double scale )
106  {
107  int n = heights.Length;
108  double step = width / ( n - 1 );
109  double maxHeight = heights.Max() * scale;
110 
111  // Each point should be adjusted by this amount in order to get the center of the shape at (0, 0)
112  // This way, drawing a single texture on top of it covers the whole shape.
113  double halfHeight = maxHeight / 2;
114 
115  Vector[] vertexes = new Vector[n * 2];
116 
117  // Let's start from the bottom right corner and head clockwise from there.
118  Vector bottomRight = new Vector( width / 2, -halfHeight );
119 
120  // Bottom vertexes, right to left
121  for ( int i = 0; i < n; i++ )
122  {
123  vertexes[i] = new Vector( bottomRight.X - ( i * step ), bottomRight.Y );
124  }
125 
126  double left = -width / 2;
127 
128  // Top vertexes, left to right
129  for ( int i = 0; i < n; i++ )
130  {
131  vertexes[n + i] = new Vector( left + ( i * step ), heights[i] * scale - halfHeight );
132  }
133 
134  return vertexes;
135  }
136 
137  private static Polygon CreateRuggedShape( double width, double[] heights, double scale )
138  {
139  Vector[] vertexes = CalculateVertexes( width, heights, scale );
140  return CreateShape( width, heights, vertexes );
141  }
142 
143  private static Polygon CreateShape( double width, double[] heights, Vector[] vertexes )
144  {
145  int n = heights.Length;
146  double step = width / ( n - 1 );
147  IndexTriangle[] triangles = new IndexTriangle[( n - 1 ) * 2];
148  Int16[] outlineIndices = new Int16[n * 2];
149 
150  for ( int i = 0; i < n * 2; i++ )
151  outlineIndices[i] = (Int16)i;
152  for ( int i = 0; i < n - 1; i++ )
153  {
154  triangles[2 * i] = new IndexTriangle( i, 2 * n - i - 2, 2 * n - i - 1 );
155  triangles[2 * i + 1] = new IndexTriangle( i, i + 1, 2 * n - i - 2 );
156  }
157 
158  Vector[] outlineVertices = new Vector[outlineIndices.Length];
159  for ( int i = 0; i < outlineIndices.Length; i++ )
160  outlineVertices[i] = vertexes[outlineIndices[i]];
161 
162  return new Polygon( new ShapeCache( vertexes, triangles, outlineIndices ), false );
163  }
164 
165  private static double GetMinHeightDifference( double[] heights )
166  {
167  int n = heights.Length;
168  double minHeightDifference = double.PositiveInfinity;
169 
170  for ( int i = 0; i < n - 1; i++ )
171  {
172  double diff = Math.Abs( heights[i + 1] - heights[i] );
173  if ( diff > double.Epsilon && diff < minHeightDifference ) minHeightDifference = diff;
174  }
175 
176  return minHeightDifference;
177  }
178 
179  #endregion
180 
181  #region Factory methods
182 
190  public static Surface Create( Level level, Direction direction )
191  {
192  if ( direction == Direction.Left ) return CreateLeft( level );
193  if ( direction == Direction.Right ) return CreateRight( level );
194  if ( direction == Direction.Up ) return CreateTop( level );
195  if ( direction == Direction.Down ) return CreateBottom( level );
196 
197  return null;
198  }
199 
210  public static Surface Create( Level level, Direction direction, double min, double max, int points )
211  {
212  if ( direction == Direction.Left ) return CreateLeft( level, min, max, points );
213  if ( direction == Direction.Right ) return CreateRight( level, min, max, points );
214  if ( direction == Direction.Up ) return CreateTop( level, min, max, points );
215  if ( direction == Direction.Down ) return CreateBottom( level, min, max, points );
216 
217  return null;
218  }
219 
231  public static Surface Create( Level level, Direction direction, double min, double max, int points, int maxchange )
232  {
233  if ( direction == Direction.Left ) return CreateLeft( level, min, max, points, maxchange );
234  if ( direction == Direction.Right ) return CreateRight( level, min, max, points, maxchange );
235  if ( direction == Direction.Up ) return CreateTop( level, min, max, points, maxchange );
236  if ( direction == Direction.Down ) return CreateBottom( level, min, max, points, maxchange );
237 
238  return null;
239  }
240 
247  public static Surface CreateLeft( Level level )
248  {
249  double thickness = level.GetBorderThickness();
250  Surface ground = new Surface( level.Height, thickness );
251  ground.Angle = -Angle.RightAngle;
252  ground.Position = new Vector( level.Left - ( thickness / 2 ), level.Center.Y );
253  return ground;
254  }
255 
265  public static Surface CreateLeft( Level level, double min, double max, int points )
266  {
267  Surface ground = new Surface( level.Height + 2 * max, min, max, points );
268  ground.Angle = -Angle.RightAngle;
269  ground.Position = new Vector( level.Left - ( max / 2 ), level.Center.Y );
270  return ground;
271  }
272 
283  public static Surface CreateLeft( Level level, double min, double max, int points, int maxchange )
284  {
285  Surface ground = new Surface( level.Height + 2 * max, min, max, points, maxchange );
286  ground.Angle = -Angle.RightAngle;
287  ground.Position = new Vector( level.Left - ( max / 2 ), level.Center.Y );
288  return ground;
289  }
290 
297  public static Surface CreateRight( Level level )
298  {
299  double thickness = level.GetBorderThickness();
300  Surface ground = new Surface( level.Height, thickness );
301  ground.Angle = Angle.RightAngle;
302  ground.Position = new Vector( level.Right + ( thickness / 2 ), level.Center.Y );
303  return ground;
304  }
305 
315  public static Surface CreateRight( Level level, double min, double max, int points )
316  {
317  Surface ground = new Surface( level.Height + 2 * max, min, max, points );
318  ground.Angle = Angle.RightAngle;
319  ground.Position = new Vector( level.Right + ( max / 2 ), level.Center.Y );
320  return ground;
321  }
322 
333  public static Surface CreateRight( Level level, double min, double max, int points, int maxchange )
334  {
335  Surface ground = new Surface( level.Height + 2 * max, min, max, points, maxchange );
336  ground.Angle = Angle.RightAngle;
337  ground.Position = new Vector( level.Right + ( max / 2 ), level.Center.Y );
338  return ground;
339  }
340 
347  public static Surface CreateTop( Level level )
348  {
349  double thickness = level.GetBorderThickness();
350  Surface ground = new Surface( level.Width + ( 2 * thickness ), thickness );
351  ground.Angle = Angle.StraightAngle;
352  ground.Position = new Vector( level.Center.X, level.Top + ( thickness / 2 ) );
353  return ground;
354  }
355 
365  public static Surface CreateTop( Level level, double min, double max, int points )
366  {
367  Surface ground = new Surface( level.Width + 2 * max, min, max, points );
368  ground.Angle = Angle.StraightAngle;
369  ground.Position = new Vector( level.Center.X, level.Top + ( max / 2 ) );
370  return ground;
371  }
372 
383  public static Surface CreateTop( Level level, double min, double max, int points, int maxchange )
384  {
385  Surface ground = new Surface( level.Width + 2 * max, min, max, points, maxchange );
386  ground.Angle = Angle.StraightAngle;
387  ground.Position = new Vector( level.Center.X, level.Top + ( max / 2 ) );
388  return ground;
389  }
390 
397  public static Surface CreateBottom( Level level )
398  {
399  double thickness = level.GetBorderThickness();
400  Surface ground = new Surface( level.Width + ( 2 * thickness ), thickness );
401  ground.Position = new Vector( level.Center.X, level.Bottom - ( thickness / 2 ) );
402  return ground;
403  }
404 
414  public static Surface CreateBottom( Level level, double min, double max, int points )
415  {
416  Surface ground = new Surface( level.Width + 2 * max, min, max, points );
417  ground.Position = new Vector( level.Center.X, level.Bottom - ( max / 2 ) );
418  return ground;
419  }
420 
431  public static Surface CreateBottom( Level level, double min, double max, int points, int maxchange )
432  {
433  Surface ground = new Surface( level.Width + 2 * max, min, max, points, maxchange );
434  ground.Position = new Vector( level.Center.X, level.Bottom - ( max / 2 ) );
435  return ground;
436  }
437 
438  #endregion
439 
440  #region Public methods
441 
442  public double GetGroundHeight( double x )
443  {
444  if ( heights == null || x < Left || x > Right ) return Top;
445 
446  int n = heights.Length;
447  double step = Width / ( n - 1 );
448  double maxHeight = heights.Max() * scale;
449 
450  double indexX = ( Width / 2 + x ) / step;
451  int lowerIndex = (int)Math.Floor( indexX );
452  int upperIndex = (int)Math.Ceiling( indexX );
453 
454  if ( upperIndex >= n ) return Top; // DEBUG
455  if ( lowerIndex == upperIndex ) return Bottom + scale * heights[lowerIndex];
456 
457  double k = ( heights[upperIndex] - heights[lowerIndex] ) / step;
458  double relX = ( Width / 2 + x ) % step;
459 
460  return Bottom + heights[lowerIndex] + relX * k;
461  }
462 
463  public Vector GetGroundNormal( double x )
464  {
465  if ( heights == null || x < Left || x > Right ) return Vector.UnitY;
466 
467  int n = heights.Length;
468  double step = Width / ( n - 1 );
469  double maxHeight = heights.Max() * scale;
470 
471  double indexX = ( Width / 2 + x ) / step;
472  int lowerIndex = (int)Math.Floor( indexX );
473  int upperIndex = (int)Math.Ceiling( indexX );
474 
475  if ( upperIndex >= n ) return Vector.UnitY; // DEBUG
476  if ( lowerIndex == upperIndex )
477  {
478  return ( GetGroundNormal( x - step / 2 ) + GetGroundNormal( x + step / 2 ) ) / 2;
479  }
480 
481  double k = ( heights[upperIndex] - heights[lowerIndex] ) / step;
483  }
484 
485  #endregion
486  }
487 }
Jypeli.Level.GetBorderThickness
double GetBorderThickness()
Definition: Borders.cs:516
Jypeli.Direction.Left
static Direction Left
Suunta vasemmalle.
Definition: Direction.cs:66
Jypeli.Surface.GetGroundHeight
double GetGroundHeight(double x)
Definition: Surface.cs:442
Jypeli.Vector.UnitY
static readonly Vector UnitY
Pystysuuntainen yksikkövektori (pituus 1, suunta ylös).
Definition: Vector.cs:78
Jypeli.Surface.CreateShape
static Polygon CreateShape(double width, double[] heights, Vector[] vertexes)
Definition: Surface.cs:143
Jypeli.Level.Height
double Height
Kentän korkeus.
Definition: Level.cs:113
Jypeli.Vector.X
double X
Definition: Vector.cs:312
Jypeli.Direction.Up
static Direction Up
Suunta ylös.
Definition: Direction.cs:56
Jypeli.Surface.GetGroundNormal
Vector GetGroundNormal(double x)
Definition: Surface.cs:463
Jypeli.Surface.scale
double scale
Definition: Surface.cs:11
Jypeli
Definition: Automobile.cs:5
Jypeli.Surface.CreateTop
static Surface CreateTop(Level level, double min, double max, int points)
Luo kentälle epätasaisen yläreunan. Ei lisää reunaa automaattisesti kenttään.
Definition: Surface.cs:365
Jypeli.ShapeCache
Sisältää valmiiksi lasketut kolmiot, joiden avulla piirtäminen on suoraviivaista.
Definition: Shapes.cs:583
Jypeli.Direction
Perussuunta tasossa.
Definition: Direction.cs:47
Jypeli.HorizontalAlignment.Center
@ Center
Keskellä.
Jypeli.Level.Width
double Width
Kentän leveys.
Definition: Level.cs:104
Jypeli.Surface.Surface
Surface(double width, double min, double max, int points)
Luo satunnaisen pinnan.
Definition: Surface.cs:72
Jypeli.Rectangle
Suorakulmio.
Definition: Shapes.cs:318
Jypeli.Shape
Kuvio.
Definition: Shapes.cs:47
Jypeli.Level.Bottom
double Bottom
Kentän alareunan y-koordinaatti.
Definition: Level.cs:155
Jypeli.Surface.CreateRight
static Surface CreateRight(Level level, double min, double max, int points)
Luo kentälle epätasaisen oikean reunan. Ei lisää reunaa automaattisesti kenttään.
Definition: Surface.cs:315
Jypeli.Color.ForestGreen
static readonly Color ForestGreen
Metsänvihreä.
Definition: Color.cs:628
Jypeli.Surface.InitializeFlat
void InitializeFlat(double height)
Definition: Surface.cs:45
Jypeli.Surface.CreateLeft
static Surface CreateLeft(Level level, double min, double max, int points)
Luo kentälle epätasaisen vasemman reunan. Ei lisää reunaa automaattisesti kenttään.
Definition: Surface.cs:265
Jypeli.Direction.Down
static Direction Down
Suunta alas.
Definition: Direction.cs:61
Jypeli.Level
Pelikenttä, johon voi lisätä olioita. Kentällä voi myös olla reunat ja taustaväri tai taustakuva.
Definition: Borders.cs:7
Jypeli.Level.Top
double Top
Kentän yläreunan y-koordinaatti.
Definition: Level.cs:147
Jypeli.Surface.Create
static Surface Create(Level level, Direction direction, double min, double max, int points)
Luo kentälle epätasaisen reunan. Ei lisää reunaa automaattisesti kenttään.
Definition: Surface.cs:210
Jypeli.Surface.Create
static Surface Create(Level level, Direction direction)
Luo kentälle tasaisen reunan. Ei lisää reunaa automaattisesti kenttään.
Definition: Surface.cs:190
Jypeli.Surface.Surface
Surface(double width, double min, double max, int points, int maxchange)
Luo satunnaisen pinnan.
Definition: Surface.cs:86
Jypeli.Angle.ArcTan
static Angle ArcTan(double d)
Palauttaa kulman joka vastaa d:n arcus-tangentti.
Definition: Angle.cs:478
Jypeli.PhysicsObject.Angle
override Angle Angle
Definition: Dimensions.cs:34
Jypeli.RandomGen
Satunnaisgeneraattori. Luo satunnaisia arvoja, mm. lukuja, vektoreita sekä kulmia.
Definition: RandomGen.cs:39
Jypeli.Surface.InitializeRugged
void InitializeRugged(double[] heights, double scale)
Definition: Surface.cs:55
Jypeli.Surface.Create
static Surface Create(Level level, Direction direction, double min, double max, int points, int maxchange)
Luo kentälle epätasaisen reunan. Ei lisää reunaa automaattisesti kenttään.
Definition: Surface.cs:231
Jypeli.Surface.GetMinHeightDifference
static double GetMinHeightDifference(double[] heights)
Definition: Surface.cs:165
Jypeli.Surface.CreateLeft
static Surface CreateLeft(Level level)
Luo kentälle tasaisen vasemman reunan. Ei lisää reunaa automaattisesti kenttään.
Definition: Surface.cs:247
Jypeli.Surface.CreateLeft
static Surface CreateLeft(Level level, double min, double max, int points, int maxchange)
Luo kentälle epätasaisen vasemman reunan. Ei lisää reunaa automaattisesti kenttään.
Definition: Surface.cs:283
Jypeli.Surface.CreateRight
static Surface CreateRight(Level level, double min, double max, int points, int maxchange)
Luo kentälle epätasaisen oikean reunan. Ei lisää reunaa automaattisesti kenttään.
Definition: Surface.cs:333
Jypeli.Level.Center
readonly Vector Center
Kentän keskipiste.
Definition: Level.cs:84
Jypeli.Surface.Surface
Surface(double width, double height)
Luo tasaisen pinnan.
Definition: Surface.cs:39
Jypeli.Color
Väri.
Definition: Color.cs:13
Jypeli.PhysicsObject.Position
override Vector Position
Definition: Dimensions.cs:27
Jypeli.Surface.CalculateVertexes
static Vector[] CalculateVertexes(double width, double[] heights, double scale)
Definition: Surface.cs:105
Jypeli.Surface.CreateRight
static Surface CreateRight(Level level)
Luo kentälle tasaisen oikean reunan. Ei lisää reunaa automaattisesti kenttään.
Definition: Surface.cs:297
Jypeli.Surface.CreateTop
static Surface CreateTop(Level level)
Luo kentälle tasaisen yläreunan. Ei lisää reunaa automaattisesti kenttään.
Definition: Surface.cs:347
Jypeli.Surface.CreateBottom
static Surface CreateBottom(Level level, double min, double max, int points)
Luo kentälle epätasaisen alareunan. Ei lisää reunaa automaattisesti kenttään.
Definition: Surface.cs:414
Jypeli.Surface.CreateRuggedShape
static Polygon CreateRuggedShape(double width, double[] heights, double scale)
Definition: Surface.cs:137
Jypeli.Polygon
Monikulmio.
Definition: Shapes.cs:502
Jypeli.Vector.FromLengthAndAngle
static Vector FromLengthAndAngle(double length, double angle)
Luo vektorin pituuden ja kulman perusteella.
Definition: Vector.cs:106
Jypeli.IndexTriangle
Muotojen määrityksessä käytettävä kolmio.
Definition: Shapes.cs:553
Jypeli.Surface.Surface
Surface(double width, double[] heights, double scale)
Helppo tapa lisätä kenttään epätasainen pinta. Pinta kuvataan luettelemalla Y-koordinaatteja vasemmal...
Definition: Surface.cs:28
Jypeli.Surface.CreateBottom
static Surface CreateBottom(Level level, double min, double max, int points, int maxchange)
Luo kentälle epätasaisen alareunan. Ei lisää reunaa automaattisesti kenttään.
Definition: Surface.cs:431
Jypeli.Vector
2D-vektori.
Definition: Vector.cs:59
System
Definition: CFFauxAttributes.cs:29
Jypeli.Angle.RightAngle
static readonly Angle RightAngle
Suora kulma (90 astetta).
Definition: Angle.cs:49
Jypeli.Surface.CreateBottom
static Surface CreateBottom(Level level)
Luo kentälle tasaisen alareunan. Ei lisää reunaa automaattisesti kenttään.
Definition: Surface.cs:397
Jypeli.Level.Right
double Right
Kentän oikean reunan x-koordinaatti.
Definition: Level.cs:139
Jypeli.PhysicsObject
Definition: Collisions.cs:6
Jypeli.Surface
Tasainen tai epätasainen pinta.
Definition: Surface.cs:9
Jypeli.Surface.CreateTop
static Surface CreateTop(Level level, double min, double max, int points, int maxchange)
Luo kentälle epätasaisen yläreunan. Ei lisää reunaa automaattisesti kenttään.
Definition: Surface.cs:383
Jypeli.Surface.CalculateHeight
static double CalculateHeight(double[] heights, double scale)
Definition: Surface.cs:95
Jypeli.Surface.heights
double[] heights
Definition: Surface.cs:10
Jypeli.Level.Left
double Left
Kentän vasemman reunan x-koordinaatti.
Definition: Level.cs:131
Jypeli.VerticalAlignment.Center
@ Center
Keskellä.
Jypeli.Direction.Right
static Direction Right
Suunta oikealle.
Definition: Direction.cs:71
Jypeli.Angle.StraightAngle
static readonly Angle StraightAngle
Oikokulma (180 astetta).
Definition: Angle.cs:54
Jypeli.Vector.Y
double Y
Definition: Vector.cs:313
Jypeli.Angle
Suuntakulma (rajoitettu -180 ja 180 asteen välille) asteina ja radiaaneina. Tietoja kulmasta: http://...
Definition: Angle.cs:40
Jypeli.PhysicsObject.MakeStatic
void MakeStatic()
Tekee oliosta staattisen eli liikkumattoman.
Definition: PhysicsObject.cs:137