Jypeli  9
The simple game programming library
AbstractTileMap.cs
Siirry tämän tiedoston dokumentaatioon.
1 using System;
2 using System.Collections.Generic;
3 using System.Linq;
4 
5 namespace Jypeli
6 {
7  public abstract class AbstractTileMap<TileType>
8  {
9  public delegate void TileMethod( Vector position, double width, double height );
10  public delegate void TileMethod<T1>( Vector position, double width, double height, T1 p1 );
11  public delegate void TileMethod<T1, T2>( Vector position, double width, double height, T1 p1, T2 p2 );
12  public delegate void TileMethod<T1, T2, T3>( Vector position, double width, double height, T1 p1, T2 p2, T3 p3 );
13 
14  public delegate void RouteMethod( List<Vector> route, double width, double height );
15 
17  {
19  public int row;
20  public int col;
21 
22  public TileMethodCall( TileMethod m, int row, int col )
23  {
24  this.method = m;
25  this.row = row;
26  this.col = col;
27  }
28 
29  public void Invoke( double tileWidth, double tileHeight )
30  {
31  double realX = Game.Instance.Level.Left + ( col * tileWidth ) + ( tileWidth / 2 );
32  double realY = Game.Instance.Level.Top - ( row * tileHeight ) - ( tileHeight / 2 );
33  method( new Vector( realX, realY ), tileWidth, tileHeight );
34  }
35  }
36 
37  private List<TileMethodCall> optimized = new List<TileMethodCall>();
38  protected Dictionary<TileType, TileMethod> legend = new Dictionary<TileType, TileMethod>();
39  protected TileType[,] tiles;
40 
41  protected abstract TileType Null { get; }
42 
43  public AbstractTileMap(TileType[,] tiles)
44  {
45  if ( tiles.GetLength( 0 ) == 0 || tiles.GetLength( 1 ) == 0 )
46  throw new ArgumentException( "All dimensions of tiles must be at least 1" );
47 
48  this.tiles = tiles;
49  }
50 
54  public int RowCount
55  {
56  get { return tiles.GetLength( 0 ); }
57  }
58 
62  public int ColumnCount
63  {
64  get { return tiles.GetLength( 1 ); }
65  }
66 
74  public void SetTileMethod( TileType tileSymbol, TileMethod f )
75  {
76  legend[tileSymbol] = f;
77  }
78 
88  public void SetTileMethod<T1>( TileType tileSymbol, TileMethod<T1> f, T1 p1 )
89  {
90  legend[tileSymbol] = delegate( Vector p, double w, double h ) { f( p, w, h, p1 ); };
91  }
92 
104  public void SetTileMethod<T1, T2>( TileType tileSymbol, TileMethod<T1, T2> f, T1 p1, T2 p2 )
105  {
106  legend[tileSymbol] = delegate( Vector p, double w, double h ) { f( p, w, h, p1, p2 ); };
107  }
108 
122  public void SetTileMethod<T1, T2, T3>( TileType tileSymbol, TileMethod<T1, T2, T3> f, T1 p1, T2 p2, T3 p3 )
123  {
124  legend[tileSymbol] = delegate( Vector p, double w, double h ) { f( p, w, h, p1, p2, p3 ); };
125  }
126 
136  public void SetRouteMethod( RouteMethod f, params TileType[] tileSymbols )
137  {
138  if ( tileSymbols == null || tileSymbols.Length < 1 )
139  throw new ArgumentException( "Pass at least one tile symbol!" );
140 
141  Vector[] vectorTable = new Vector[tileSymbols.Length];
142  int vectorsAdded = 0;
143 
144  for ( int i = 0; i < tileSymbols.Length; i++ )
145  {
146  int index = i;
147  legend[tileSymbols[i]] = delegate( Vector p, double w, double h )
148  {
149  vectorTable[index] = p;
150  if ( ++vectorsAdded >= tileSymbols.Length )
151  f( vectorTable.ToList(), w, h );
152  };
153  }
154  }
155 
163  public void Execute()
164  {
165  double h = Game.Instance.Level.Height / tiles.GetLength( 0 );
166  double w = Game.Instance.Level.Width / tiles.GetLength( 1 );
167  Execute( w, h );
168  }
169 
179  public void Execute( double tileWidth, double tileHeight )
180  {
181  Game game = Game.Instance;
182  int width = tiles.GetLength( 1 );
183  int height = tiles.GetLength( 0 );
184 
185  game.Level.Width = width * tileWidth;
186  game.Level.Height = height * tileHeight;
187 
188  foreach ( var m in optimized )
189  {
190  m.Invoke( tileWidth, tileHeight );
191  }
192 
193  for ( int y = height - 1; y >= 0; y-- )
194  {
195  for ( int x = 0; x < width; x++ )
196  {
197  TileMethod method = GetMethodForSymbol( tiles[y, x] );
198 
199  if ( method != null )
200  {
201  double realX = game.Level.Left + ( x * tileWidth ) + ( tileWidth / 2 );
202  double realY = game.Level.Top - ( y * tileHeight ) - ( tileHeight / 2 );
203  method( new Vector( realX, realY ), tileWidth, tileHeight );
204  }
205  }
206  }
207  }
208 
209  protected TileMethod GetMethodForSymbol( TileType symbol )
210  {
211  if ( symbol.Equals(Null) ) return null;
212 
213  foreach ( var key in legend.Keys )
214  {
215  if ( SymbolEquals( key, symbol ) )
216  return legend[key];
217  }
218 
219  return null;
220  }
221 
222  protected virtual bool SymbolEquals( TileType a, TileType b )
223  {
224  return a.Equals( b );
225  }
226 
232  public void Optimize( params TileType[] symbols )
233  {
234  for ( int i = 0; i < symbols.Length; i++ )
235  Optimize( symbols[i] );
236  }
237 
243  public void Optimize( TileType sym )
244  {
245  TileMethod method = GetMethodForSymbol(sym);
246 
247  if (method == null)
248  throw new ArgumentException("Symbol " + sym + " not added, cannot optimize.");
249 
250  for ( int row = 0; row < RowCount; row++ )
251  {
252  for ( int col = 0; col < ColumnCount; col++ )
253  {
254  int w, h;
255  GetGreatestMatchingRectangle( sym, row, col, out w, out h );
256 
257  if ( w > 0 && h > 0 )
258  {
259  TileMethod newMethod = delegate (Vector oldPos, double oldWidth, double oldHeight)
260  {
261  Vector oldAdjust = new Vector(-oldWidth, oldHeight);
262  Vector newAdjust = new Vector(oldWidth * w, -oldHeight * h);
263  Vector newPos = oldPos + ( oldAdjust + newAdjust ) / 2;
264  method( newPos, oldWidth * w, oldHeight * h );
265  };
266  optimized.Add( new TileMethodCall( newMethod, row, col ) );
267  SetArea( row, col, w, h, Null );
268  col += w;
269  }
270  }
271  }
272  }
273 
274  private void GetGreatestMatchingRectangle( TileType sym, int row, int col, out int width, out int height )
275  {
276  for ( width = 0; width < ColumnCount - col; width++ )
277  {
278  if ( !SymbolEquals( tiles[row, col + width], sym ) )
279  break;
280  }
281 
282  if ( width == 0 )
283  {
284  height = 0;
285  return;
286  }
287 
288  for ( height = 1; height < RowCount - row; height++ )
289  {
290  if ( !RowEquals( row + height, col, width, sym ) )
291  break;
292  }
293  }
294 
295  private bool RowEquals( int row, int col, int length, TileType sym )
296  {
297  for ( int i = col; i < col + length; i++ )
298  {
299  if ( !SymbolEquals( tiles[row, i], sym ) ) return false;
300  }
301 
302  return true;
303  }
304 
305  private void SetArea( int row, int col, int width, int height, TileType sym )
306  {
307  for ( int j = row; j < row + height; j++ )
308  {
309  for ( int i = col; i < col + width; i++ )
310  {
311  tiles[j, i] = sym;
312  }
313  }
314  }
315 
321  public int GetLength( int dimension )
322  {
323  return tiles.GetLength( dimension );
324  }
325 
332  public TileType GetTile( int row, int col )
333  {
334  return tiles[row,col];
335  }
336 
344  public void SetTile( int row, int col, TileType c )
345  {
346  tiles[row,col] = c;
347  }
348 
356  public static TileMethod ChangeSize( TileMethod m, double newWidth, double newHeight )
357  {
358  return new TileMethod( delegate( Vector p, double w, double h ) { m( p, newWidth, newHeight ); } );
359  }
360 
368  public static TileMethod ChangeSizeMultiplier( TileMethod m, double widthMultiplier, double heightMultiplier )
369  {
370  return new TileMethod( delegate( Vector p, double w, double h ) { m( p, w * widthMultiplier, h * heightMultiplier ); } );
371  }
372  }
373 }
Jypeli.AbstractTileMap.TileMethod< T1, T2 >
delegate void TileMethod< T1, T2 >(Vector position, double width, double height, T1 p1, T2 p2)
Jypeli.AbstractTileMap.TileMethodCall.Invoke
void Invoke(double tileWidth, double tileHeight)
Definition: AbstractTileMap.cs:29
Jypeli.AbstractTileMap.optimized
List< TileMethodCall > optimized
Definition: AbstractTileMap.cs:37
Jypeli.AbstractTileMap.SetTile
void SetTile(int row, int col, TileType c)
Asettaa ruudussa olevan symbolin.
Definition: AbstractTileMap.cs:344
Jypeli.AbstractTileMap.ColumnCount
int ColumnCount
Sarakkeiden määrä kentässä (vaakasuoraan).
Definition: AbstractTileMap.cs:63
Jypeli.Level.Height
double Height
Kentän korkeus.
Definition: Level.cs:113
Jypeli.AbstractTileMap.TileMethodCall
Definition: AbstractTileMap.cs:17
Jypeli
Definition: Automobile.cs:5
Jypeli.AbstractTileMap.TileMethodCall.row
int row
Definition: AbstractTileMap.cs:19
Jypeli.AbstractTileMap.AbstractTileMap
AbstractTileMap(TileType[,] tiles)
Definition: AbstractTileMap.cs:43
Jypeli.Level.Width
double Width
Kentän leveys.
Definition: Level.cs:104
Jypeli.AbstractTileMap.TileMethodCall.method
TileMethod method
Definition: AbstractTileMap.cs:18
Jypeli.AbstractTileMap.TileMethod< T1, T2, T3 >
delegate void TileMethod< T1, T2, T3 >(Vector position, double width, double height, T1 p1, T2 p2, T3 p3)
Jypeli.AbstractTileMap.Null
abstract TileType Null
Definition: AbstractTileMap.cs:41
Jypeli.AbstractTileMap.TileMethodCall.TileMethodCall
TileMethodCall(TileMethod m, int row, int col)
Definition: AbstractTileMap.cs:22
Jypeli.AbstractTileMap.TileMethod
delegate void TileMethod(Vector position, double width, double height)
Jypeli.AbstractTileMap.TileMethodCall.col
int col
Definition: AbstractTileMap.cs:20
Jypeli.AbstractTileMap.SymbolEquals
virtual bool SymbolEquals(TileType a, TileType b)
Definition: AbstractTileMap.cs:222
Jypeli.Level.Top
double Top
Kentän yläreunan y-koordinaatti.
Definition: Level.cs:147
Jypeli.AbstractTileMap.GetLength
int GetLength(int dimension)
Palauttaa annetun dimension pituuden (merkkeinä, ei pikseleinä).
Definition: AbstractTileMap.cs:321
Jypeli.AbstractTileMap.RouteMethod
delegate void RouteMethod(List< Vector > route, double width, double height)
Jypeli.Game.Instance
static Game Instance
Käynnissä olevan pelin pääolio.
Definition: Game.cs:90
Jypeli.AbstractTileMap.SetArea
void SetArea(int row, int col, int width, int height, TileType sym)
Definition: AbstractTileMap.cs:305
Jypeli.AbstractTileMap.ChangeSize
static TileMethod ChangeSize(TileMethod m, double newWidth, double newHeight)
Muuttaa luontialiohjelman tekemän olion kokoa.
Definition: AbstractTileMap.cs:356
Jypeli.AbstractTileMap.Execute
void Execute()
Käy kentän kaikki merkit läpi ja kutsuu SetTileMethod-metodilla annettuja aliohjelmia kunkin merkin k...
Definition: AbstractTileMap.cs:163
Jypeli.AbstractTileMap.SetTileMethod< T1 >
void SetTileMethod< T1 >(TileType tileSymbol, TileMethod< T1 > f, T1 p1)
Määrittää, että tietyn ruutukentän symbolin (tileSymbol) kohdalla kutsutaan aliohjelmaa f....
Definition: AbstractTileMap.cs:88
Jypeli.AbstractTileMap.Optimize
void Optimize(TileType sym)
Optimoi annetut ruudut niin, että useammat vierekkäiset oliot yhdistetään isommiksi olioiksi....
Definition: AbstractTileMap.cs:243
Jypeli.AbstractTileMap.SetTileMethod< T1, T2 >
void SetTileMethod< T1, T2 >(TileType tileSymbol, TileMethod< T1, T2 > f, T1 p1, T2 p2)
Määrittää, että tietyn ruutukentän symbolin (tileSymbol) kohdalla kutsutaan aliohjelmaa f....
Definition: AbstractTileMap.cs:104
Jypeli.AbstractTileMap.tiles
TileType[,] tiles
Definition: AbstractTileMap.cs:39
Jypeli.AbstractTileMap.RowCount
int RowCount
Rivien määrä kentässä (pystysuoraan).
Definition: AbstractTileMap.cs:55
Jypeli.AbstractTileMap
Definition: AbstractTileMap.cs:8
Jypeli.AbstractTileMap.SetTileMethod< T1, T2, T3 >
void SetTileMethod< T1, T2, T3 >(TileType tileSymbol, TileMethod< T1, T2, T3 > f, T1 p1, T2 p2, T3 p3)
Määrittää, että tietyn ruutukentän symbolin (tileSymbol) kohdalla kutsutaan aliohjelmaa f....
Definition: AbstractTileMap.cs:122
Jypeli.Vector
2D-vektori.
Definition: Vector.cs:59
System
Definition: CFFauxAttributes.cs:29
Jypeli.AbstractTileMap.GetGreatestMatchingRectangle
void GetGreatestMatchingRectangle(TileType sym, int row, int col, out int width, out int height)
Definition: AbstractTileMap.cs:274
Jypeli.AbstractTileMap.RowEquals
bool RowEquals(int row, int col, int length, TileType sym)
Definition: AbstractTileMap.cs:295
Jypeli.Level.Left
double Left
Kentän vasemman reunan x-koordinaatti.
Definition: Level.cs:131
Jypeli.AbstractTileMap.Optimize
void Optimize(params TileType[] symbols)
Optimoi annetut ruudut niin, että useammat vierekkäiset oliot yhdistetään isommiksi olioiksi....
Definition: AbstractTileMap.cs:232
Jypeli.AbstractTileMap.TileMethod< T1 >
delegate void TileMethod< T1 >(Vector position, double width, double height, T1 p1)
Jypeli.AbstractTileMap.legend
Dictionary< TileType, TileMethod > legend
Definition: AbstractTileMap.cs:38
Jypeli.AbstractTileMap.SetTileMethod
void SetTileMethod(TileType tileSymbol, TileMethod f)
Määrittää, että tietyn ruutukentän symbolin (tileSymbol) kohdalla kutsutaan aliohjelmaa f....
Definition: AbstractTileMap.cs:74
Jypeli.AbstractTileMap.GetMethodForSymbol
TileMethod GetMethodForSymbol(TileType symbol)
Definition: AbstractTileMap.cs:209
Jypeli.AbstractTileMap.ChangeSizeMultiplier
static TileMethod ChangeSizeMultiplier(TileMethod m, double widthMultiplier, double heightMultiplier)
Muuttaa luontialiohjelman tekemän olion kokoa tietyllä kertoimilla.
Definition: AbstractTileMap.cs:368
Jypeli.AbstractTileMap.GetTile
TileType GetTile(int row, int col)
Palauttaa ruudussa olevan symbolin.
Definition: AbstractTileMap.cs:332
Jypeli.AbstractTileMap.SetRouteMethod
void SetRouteMethod(RouteMethod f, params TileType[] tileSymbols)
Kokoaa reitin useammasta ruutukentän symbolista.
Definition: AbstractTileMap.cs:136
Jypeli.AbstractTileMap.Execute
void Execute(double tileWidth, double tileHeight)
Käy kentän kaikki merkit läpi ja kutsuu SetTileMethod-metodilla annettuja aliohjelmia kunkin merkin k...
Definition: AbstractTileMap.cs:179
Jypeli.Game
Definition: Content.cs:46
Jypeli.Game.Level
Level Level
Aktiivinen kenttä.
Definition: Game.cs:133