Final-Bomber  0.1
Bomberman/Dynablaster remake in C# using XNA.
 All Classes Namespaces Files Functions Variables Enumerations Enumerator Properties Events Pages
Bomb.cs
Go to the documentation of this file.
1 using System;
2 using System.Collections.Generic;
3 using System.Diagnostics;
4 using FBLibrary.Core;
5 using FBLibrary.Core.BaseEntities;
6 using FBClient.Sprites;
7 using Microsoft.Xna.Framework;
8 using Microsoft.Xna.Framework.Audio;
9 using Microsoft.Xna.Framework.Graphics;
10 
11 namespace FBClient.Core.Entities
12 {
13  public class Bomb : BaseBomb
14  {
15  #region Field Region
16 
17  private readonly Animation[] _explosionAnimations;
18  private readonly Dictionary<Point, ExplosionDirection> _explosionAnimationsDirection;
19  private readonly Texture2D _explosionSpriteTexture;
20 
21  // Sounds
22  private SoundEffect _bombExplosionSound;
23 
24 
25  public AnimatedSprite Sprite { get; protected set; }
26 
27  // TODO: Move to base bomb
28  private bool _cellTeleporting;
29  private int _lastPlayerThatPushIt;
30 
31  private enum ExplosionDirection
32  {
33  Down,
34  Left,
35  Right,
36  Up,
37  Middle,
38  Horizontal,
39  Vertical
40  };
41 
42  #endregion
43 
44  #region Constructor Region
45 
46  public Bomb(int playerId, Point cellPosition, int pow, TimeSpan timer, float playerSpeed)
47  : base(playerId, cellPosition, pow, timer, playerSpeed)
48  {
49  // TODO: Move all loading of content into a LoadContent XNA method like
50  // Bomb Sprite
51  var spriteTexture = FinalBomber.Instance.Content.Load<Texture2D>("Graphics/Characters/bomb");
52  var animation = new Animation(3, 32, 32, 0, 0, 3);
53  Sprite = new AnimatedSprite(spriteTexture, animation)
54  {
55  IsAnimating = true
56  };
57 
58  // Bomb's explosion animations
59  _explosionSpriteTexture = FinalBomber.Instance.Content.Load<Texture2D>("Graphics/Characters/explosion");
60  const int explosionAnimationsFramesPerSecond = 10;
61  _explosionAnimations = new[]
62  {
63  new Animation(4, 32, 32, 0, 0, explosionAnimationsFramesPerSecond),
64  new Animation(4, 32, 32, 0, 32, explosionAnimationsFramesPerSecond),
65  new Animation(4, 32, 32, 0, 64, explosionAnimationsFramesPerSecond),
66  new Animation(4, 32, 32, 0, 96, explosionAnimationsFramesPerSecond),
67  new Animation(4, 32, 32, 0, 128, explosionAnimationsFramesPerSecond),
68  new Animation(4, 32, 32, 0, 160, explosionAnimationsFramesPerSecond),
69  new Animation(4, 32, 32, 0, 192, explosionAnimationsFramesPerSecond)
70  };
71 
72  _explosionAnimationsDirection = new Dictionary<Point, ExplosionDirection>();
73 
74  // Bomb's states
75  _cellTeleporting = false;
76  _lastPlayerThatPushIt = -1;
77 
78  // Sounds
79  _bombExplosionSound = FinalBomber.Instance.Content.Load<SoundEffect>("Audio/Sounds/boom");
80  }
81 
82  #endregion
83 
84  #region XNA Method
85 
86  public void Update(GameTime gameTime)
87  {
88  Sprite.Update(gameTime);
89 
90  #region Is moving ?
91  /*
92  if (IsChangingCell())
93  {
94  if (Map.Board[PreviousCellPosition.X, PreviousCellPosition.Y] == this)
95  {
96  Map.Board[PreviousCellPosition.X, PreviousCellPosition.Y] = null;
97  }
98 
99  if (Map.Board[CellPosition.X, CellPosition.Y] == null)
100  {
101  Map.CollisionLayer[CellPosition.X, CellPosition.Y] = true;
102  Map.Board[CellPosition.X, CellPosition.Y] = this;
103  }
104 
105  Map.CollisionLayer[PreviousCellPosition.X, PreviousCellPosition.Y] = false;
106 
107  if (_cellTeleporting)
108  _cellTeleporting = false;
109 
110  Position = Engine.CellToVector(CellPosition);
111  }
112  */
113  #endregion
114 
115  #region Destruction
116 
117  if (InDestruction)
118  {
119  foreach (Animation animation in _explosionAnimations)
120  animation.Update(gameTime);
121  }
122 
123  Debug.Print(Timer.ToString());
124 
125  #endregion
126 
127  #region When the bomb moves
128  /*
129  // Control
130  if (InputHandler.KeyDown(Keys.NumPad8))
131  CurrentDirection = LookDirection.Up;
132  else if (InputHandler.KeyDown(Keys.NumPad5))
133  CurrentDirection = LookDirection.Down;
134  else if (InputHandler.KeyDown(Keys.NumPad4))
135  CurrentDirection = LookDirection.Left;
136  else if (InputHandler.KeyDown(Keys.NumPad6))
137  CurrentDirection = LookDirection.Right;
138 
139  if (CurrentDirection != LookDirection.Idle)
140  {
141  switch (CurrentDirection)
142  {
143  case LookDirection.Up:
144  if (Position.Y > Engine.TileHeight)
145  PositionY = Position.Y - Speed;
146  else
147  CurrentDirection = LookDirection.Idle;
148 
149  var upCell = new Point(CellPosition.X, CellPosition.Y - 1);
150  if (Map.Board[upCell.X, upCell.Y] is Player || WallAt(upCell))
151  {
152  // Top collision
153  if (CurrentDirection == LookDirection.Up && MoreTopSide())
154  {
155  PositionY = CellPosition.Y*Engine.TileHeight;
156  CurrentDirection = LookDirection.Idle;
157  }
158  }
159 
160  break;
161  case LookDirection.Down:
162  if (Position.Y < (MapSize.Y - 2)*Engine.TileHeight)
163  PositionY = Position.Y + Speed;
164  else
165  CurrentDirection = LookDirection.Idle;
166 
167  var bottomCell = new Point(CellPosition.X, CellPosition.Y + 1);
168  if (Map.Board[bottomCell.X, bottomCell.Y] is Player || WallAt(bottomCell))
169  {
170  // Bottom collision
171  if (CurrentDirection == LookDirection.Down && MoreBottomSide())
172  {
173  PositionY = CellPosition.Y*Engine.TileHeight;
174  CurrentDirection = LookDirection.Idle;
175  }
176  }
177 
178  break;
179  case LookDirection.Left:
180  if (Position.X > Engine.TileWidth)
181  PositionX = Position.X - Speed;
182  else
183  CurrentDirection = LookDirection.Idle;
184 
185  var leftCell = new Point(CellPosition.X - 1, CellPosition.Y);
186  if (Map.Board[leftCell.X, leftCell.Y] is Player || WallAt(leftCell))
187  {
188  // Left collision
189  if (CurrentDirection == LookDirection.Left && MoreLeftSide())
190  {
191  PositionX = CellPosition.X*Engine.TileWidth - Engine.TileWidth/2 +
192  Engine.TileWidth/2;
193  CurrentDirection = LookDirection.Idle;
194  }
195  }
196  break;
197  case LookDirection.Right:
198  if (Position.X < (MapSize.X - 2)*Engine.TileWidth)
199  PositionX = Position.X + Speed;
200  else
201  CurrentDirection = LookDirection.Idle;
202 
203  var rightCell = new Point(CellPosition.X + 1, CellPosition.Y);
204  if (Map.Board[rightCell.X, rightCell.Y] is Player || WallAt(rightCell))
205  {
206  // Right collision
207  if (CurrentDirection == LookDirection.Right && MoreRightSide())
208  {
209  PositionX = CellPosition.X*Engine.TileWidth - Engine.TileWidth/2 +
210  Engine.TileWidth/2;
211  CurrentDirection = LookDirection.Idle;
212  }
213  }
214  break;
215  }
216  if (CurrentDirection == LookDirection.Idle)
217  Position = Engine.CellToVector(CellPosition);
218  }
219  */
220  #endregion
221 
222  #region Teleporter
223  /*
224  if (!_cellTeleporting && Map.
225  Board[CellPosition.X, CellPosition.Y] is Teleporter)
226  {
227  var teleporter = (Teleporter) (Map.
228  Board[CellPosition.X, CellPosition.Y]);
229 
230  teleporter.ChangeEntityPosition(this, Map);
231  _cellTeleporting = true;
232  }
233  */
234  #endregion
235 
236  #region Arrow
237  /*
238  if (!_cellTeleporting && Map.
239  Board[CellPosition.X, CellPosition.Y] is Arrow)
240  {
241  var arrow = (Arrow) (Map.Board[CellPosition.X, CellPosition.Y]);
242 
243  arrow.ChangeDirection(this);
244  }
245  */
246  #endregion
247 
248  // Call Update method of DynamicEntity class
249  base.Update();
250  }
251 
252  public void Draw(GameTime gameTime)
253  {
254  if (InDestruction)
255  {
256  if (_explosionAnimationsDirection.Count == 0)
257  {
258  foreach (Point p in ActionField)
259  {
260  // Is this a wall ? => we don't like wall !
261  if (!CollisionLayer[p.X, p.Y] || p == CellPosition)
262  {
263  // We choose the sprite of explosion for each cell
264  _explosionAnimationsDirection[p] = ComputeExplosionSpriteDirections(p, HazardMap);
265  }
266  }
267  }
268  else
269  {
270  foreach (Point p in _explosionAnimationsDirection.Keys)
271  {
272  FinalBomber.Instance.SpriteBatch.Draw(_explosionSpriteTexture,
273  new Vector2(Engine.Origin.X + p.X*Engine.TileWidth, Engine.Origin.Y + p.Y*Engine.TileHeight),
274  _explosionAnimations[(int) _explosionAnimationsDirection[p]].CurrentFrameRect, Color.White);
275  }
276  }
277  }
278  else
279  Sprite.Draw(gameTime, FinalBomber.Instance.SpriteBatch, Position);
280  }
281 
282  #endregion
283 
284  #region Method Region
285 
286  #region Private Method Region
287 
288  #region Moving utils methods
289 
290  private bool WallAt(Point cell)
291  {
292  if (cell.X >= 0 && cell.Y >= 0 && cell.X < MapSize.X &&
293  cell.Y < MapSize.Y)
294  return (CollisionLayer[cell.X, cell.Y]);
295  return false;
296  }
297 
298  private bool MoreTopSide()
299  {
300  return Position.Y < ((CellPosition.Y * Engine.TileHeight) - (Speed / 2));
301  }
302 
303  private bool MoreBottomSide()
304  {
305  return Position.Y > ((CellPosition.Y * Engine.TileHeight) + (Speed / 2));
306  }
307 
308  private bool MoreLeftSide()
309  {
310  return Position.X < ((CellPosition.X * Engine.TileWidth) - (Speed / 2));
311  }
312 
313  private bool MoreRightSide()
314  {
315  return Position.X > ((CellPosition.X * Engine.TileWidth) + (Speed / 2));
316  }
317 
318  #endregion
319 
320  // 0 => Down, 1 => Left, 2 => Right, 3 => Up, 4 => Middle, 5 => Horizontal, 6 => Vertical
321  private ExplosionDirection ComputeExplosionSpriteDirections(Point cell, int[,] hazardMap)
322  {
323  int downCell = cell.Y + 1, leftCell = cell.X - 1, rightCell = cell.X + 1, upCell = cell.Y - 1;
324 
325  // ~ The middle ~ //
326  if (cell.X == CellPosition.X && cell.Y == CellPosition.Y)
327  return ExplosionDirection.Middle;
328 
329  // ~ Vertical axis ~ //
330 
331  // Top extremity
332  if (hazardMap[cell.X, upCell] == 0 &&
333  (ActionField.Find(c => c.X == cell.X && c.Y == downCell) != Point.Zero))
334  return ExplosionDirection.Up;
335  // Vertical
336  if ((ActionField.Find(c => c.X == cell.X && c.Y == downCell) != Point.Zero) &&
337  (ActionField.Find(c => c.X == cell.X && c.Y == upCell) != Point.Zero))
338  return ExplosionDirection.Vertical;
339  // Bottom extremity
340  if (hazardMap[cell.X, downCell] == 0 &&
341  (ActionField.Find(c => c.X == cell.X && c.Y == upCell) != Point.Zero))
342  return ExplosionDirection.Down;
343 
344  // ~ Horizontal axis ~ //
345 
346  // Left extremity
347  if (hazardMap[leftCell, cell.Y] == 0 &&
348  (ActionField.Find(c => c.X == rightCell && c.Y == cell.Y) != Point.Zero))
349  return ExplosionDirection.Left;
350  // Left - Right
351  if ((ActionField.Find(c => c.X == rightCell && c.Y == cell.Y) != Point.Zero) &&
352  (ActionField.Find(c => c.X == leftCell && c.Y == cell.Y) != Point.Zero))
353  return ExplosionDirection.Horizontal;
354  // Right extremity
355  if (hazardMap[rightCell, cell.Y] == 0 &&
356  (ActionField.Find(c => c.X == leftCell && c.Y == cell.Y) != Point.Zero))
357  return ExplosionDirection.Right;
358 
359  // ~ Corners ~ //
360 
361  // Corner Top - Left
362  if (cell.Y == 1 && cell.X == 1)
363  {
364  // Left extremity
365  if (ActionField.Find(c => c.X == rightCell && c.Y == cell.Y) != Point.Zero)
366  return ExplosionDirection.Left;
367  // Top extremity
368  return ExplosionDirection.Up;
369  }
370  // Corner Bottom - Left
371  if (cell.Y == MapSize.Y - 2 && cell.X == 1)
372  {
373  // Left extremity
374  return ActionField.Find(c => c.X == rightCell && c.Y == cell.Y) != Point.Zero
375  ? ExplosionDirection.Left
376  : ExplosionDirection.Down;
377  }
378 
379  // Corner Top - Right
380  if (cell.X == MapSize.X - 2 && cell.Y == 1)
381  {
382  // Right extremity
383  return ActionField.Find(c => c.X == leftCell && c.Y == cell.Y) != Point.Zero
384  ? ExplosionDirection.Right
385  : ExplosionDirection.Up;
386  }
387  // Corner Bottom - Right
388  if (cell.Y == MapSize.Y - 2 && cell.X == MapSize.X - 2)
389  {
390  // Right extremity
391  return ActionField.Find(c => c.X == leftCell && c.Y == cell.Y) != Point.Zero
392  ? ExplosionDirection.Right
393  : ExplosionDirection.Down;
394  }
395  // Error case
396  return ExplosionDirection.Middle;
397  }
398 
399  #endregion
400 
401  #region Public Method Region
402 
403  public void ChangeDirection(LookDirection lD, int playerId)
404  {
405  Point pos = Point.Zero;
406  switch (lD)
407  {
408  case LookDirection.Up:
409  pos = new Point(CellPosition.X, CellPosition.Y - 1);
410  break;
411  case LookDirection.Down:
412  pos = new Point(CellPosition.X, CellPosition.Y + 1);
413  break;
414  case LookDirection.Left:
415  pos = new Point(CellPosition.X - 1, CellPosition.Y);
416  break;
417  case LookDirection.Right:
418  pos = new Point(CellPosition.X + 1, CellPosition.Y);
419  break;
420  }
421 
422  if (!CollisionLayer[pos.X, pos.Y])
423  {
424  CurrentDirection = lD;
425  _lastPlayerThatPushIt = playerId;
426  foreach (Point p in ActionField)
427  {
428  HazardMap[p.X, p.Y] = 0;
429  }
430  }
431  else
432  CurrentDirection = LookDirection.Idle;
433  }
434 
435  public override void Destroy()
436  {
437  _bombExplosionSound.Play();
438 
439  base.Destroy();
440  }
441 
442  public override void Remove()
443  {
444  base.Remove();
445  }
446 
447  #endregion
448 
449  #endregion
450  }
451 }
void Update(GameTime gameTime)
Definition: Bomb.cs:86
static Vector2 Origin
Definition: Engine.cs:75
void ChangeDirection(LookDirection lD, int playerId)
Definition: Bomb.cs:403
Bomb(int playerId, Point cellPosition, int pow, TimeSpan timer, float playerSpeed)
Definition: Bomb.cs:46
override void Remove()
Definition: Bomb.cs:442
void Draw(GameTime gameTime)
Definition: Bomb.cs:252
override void Destroy()
Definition: Bomb.cs:435
static int TileWidth
Definition: Engine.cs:65
static int TileHeight
Definition: Engine.cs:70