/// <summary>Создаёт новый экземпляр класса <see cref="Movement"/>.</summary> /// <param name="board">Вся доска.</param> /// <param name="state">Прямоугольник отрисовки.</param> /// <param name="current">Текущая ячейка.</param> /// <param name="speed">Скорость перемещения.</param> /// <param name="sprite">Анимация объекта.</param> /// <param name="animation">Параметры анимации объекта.</param> public Movement(Rectangle state, Cell current, int speed, AnimateSprite sprite, PlayerAnimation animation, bool IsMagic) { IsEnd = true; _CurrentState = state; _Current = current; _Speed = speed; _Tile = sprite; _Animation = animation; _Field = Helper.Field; _Field = new PathNode[Helper.Board.GetLength(0), Helper.Board.GetLength(1)]; bool pass; for (int i = 0; i < Helper.Board.GetLength(0); i++) for (int j = 0; j < Helper.Board.GetLength(1); j++) { if (IsMagic) pass = false; else pass = (Helper.Board[i, j].Type != CellType.Passable); _Field[i, j] = new PathNode() { IsWall = pass , X = Helper.Board[i, j].Rect.X, Y = Helper.Board[i, j].Rect.Y, i = i, j = j, }; } }
/// <summary>Загружает параметры игрока из XML-файла</summary> /// <param name="node">Запись об игроке.</param> /// <param name="game">Ссылка на игру.</param> public void LoadPlayerParameters(XmlNode node, SourceryGame game) { //Читаем параметры из *.lvl string playerName = node.SelectSingleNode("Name").InnerText; string fileName = node.SelectSingleNode("File").InnerText; int x = Convert.ToInt32(node.SelectSingleNode("x").InnerText); int y = Convert.ToInt32(node.SelectSingleNode("y").InnerText); int startAnimation = Convert.ToInt32(node.SelectSingleNode("StartAnimation").InnerText); var type = node.SelectSingleNode("Type").InnerText; PlayerType playerType = (PlayerType)Enum.Parse(typeof(PlayerType), type); type = node.SelectSingleNode("Color").InnerText; Colors color = (Colors)Enum.Parse(typeof(Colors), type); //Читаем параметры героя XmlDocument doc = new XmlDocument(); doc.Load("data/players/" + fileName); string textureName = doc.SelectSingleNode("Player/Texture").InnerText; int width = int.Parse(doc.SelectSingleNode("Player/width").InnerText); int height = int.Parse(doc.SelectSingleNode("Player/height").InnerText); int speed = int.Parse(doc.SelectSingleNode("Player/speed").InnerText); _Animation = new PlayerAnimation(doc.SelectSingleNode("Player/Animation")); //Задаем начальные параметры _Tile = new AnimateSprite(game.Content.Load<Texture2D>("animation/" + textureName), 8, 24); _Tile.CurrentFrame = startAnimation; LoadColor(color); _CurrentState = new Rectangle(x-width/2, y-height/2, width, height); _Type = playerType; if (playerName == "") Name = game.PlayerName; else Name = playerName; foreach (Cell cell in Helper.Board) if (cell.Rect.Contains(x, y)) { _CurrentCell = cell; break; } CurrentMagic = MaxMagic; _Movement = new Movement(_CurrentState, _CurrentCell, speed, _Tile, _Animation,false); }
/// <summary>Рисует персонажа</summary> public void Draw(SpriteBatch spriteBatch) { _CurrentState = _Movement.CurrentState; _CurrentCell = _Movement.CurrentCell; _Tile.Draw(spriteBatch, _CurrentState); spriteBatch.DrawString(_Font, Name, new Vector2(_CurrentState.X + 10, _CurrentState.Y + 10), _Color); if (DrawEnemySelector) spriteBatch.Draw(_EnemySelector, _CurrentState,Color.White); if (DrawOurSelector) spriteBatch.Draw(_OurSelector, _CurrentState, Color.White); }
/// <summary>Загружаем уровень из XML</summary> /// <param name="name">Имя файла.</param> /// <exception cref="System.ArgumentException"> /// Уровень не найден или Уровень задан некорректно /// </exception> private void LoadXmlAttributes(string name) { //Проверим существование файла string path = "data/levels/" + name + ".lvl"; if (!File.Exists(path)) throw new ArgumentException("Уровень "+name+" не найден"); //Создадим документ XmlDocument document; document = new XmlDocument(); document.Load(path); //Получаем свойства _Name = GetXmlValue(document,"Level/Name"); var mapName = GetXmlValue(document, "Level/Texture"); _Map = Helper.Game.Content.Load<Texture2D>("maps/" + mapName); if (_Map==null) throw new ArgumentException("Уровень " + name + " задан некорректно"); int width = Convert.ToInt32(GetXmlValue(document,"Level/Width")); int height = Convert.ToInt32(GetXmlValue(document,"Level/Height")); if (width == 0 || height == 0) throw new ArgumentException("Уровень " + name + " задан некорректно"); _BoardWidth = width; _BoardHeight = height; //Загружаем доску _Board = new Cell[width,height]; var lines = document.SelectNodes("Level/Board/Line"); if (lines==null) throw new ArgumentException("Уровень " + name + " задан некорректно"); int i = 0; CellType type = CellType.Passable; foreach (XmlNode node in lines) { var st = node.InnerText; for (int j = 0; j < width; j++) { int k = int.Parse(st[j].ToString()); switch (k) { case 0: { type = CellType.Impassable; break; } case 1: { type = CellType.Passable; break; } case 2: { type = CellType.Town; break; } case 3: { type = CellType.Castle; break; } } var Cell = new Cell(new Point(j, i), type, Helper.ScreenWidth / width, Helper.ScreenHeight / height); _Board[j, i] = Cell; } i++; } Helper.Board = _Board; LoadCastles(document); LoadTowers(document); LoadPlayers(document); LoadPlayersCastles(); }
/// <summary>Возвращает ближайшую клетку</summary> private Cell GetNearestCell(Cell current) { if (_SelectedMagic == null) return null; int Radius = _SelectedMagic.Radius; int max = Radius / (Helper.ScreenWidth / _BoardWidth); Point PlayerCell = new Point(_Players[0].Position.i, _Players[0].Position.j); Point TargetCell = new Point(current.i, current.j); int deltaX = Math.Abs(PlayerCell.X - TargetCell.X); int deltaY =Math.Abs( PlayerCell.Y - TargetCell.Y); int delta = 0; int newDelta = 0; while (max > 0) { if (deltaX > max & deltaY < max) { delta = deltaX - max; if ((PlayerCell.X > TargetCell.X) && (_Board[PlayerCell.X - max, PlayerCell.Y] != null) && _Board[PlayerCell.X - max, PlayerCell.Y].Type!=CellType.Impassable) return _Board[PlayerCell.X - delta, PlayerCell.Y]; else if ((PlayerCell.X < TargetCell.X) && (_Board[PlayerCell.X + max, PlayerCell.Y] != null) && _Board[PlayerCell.X + max, PlayerCell.Y].Type != CellType.Impassable) return _Board[PlayerCell.X + delta, PlayerCell.Y]; } if (deltaY > max & deltaX < max) { delta = deltaY - max; if ((PlayerCell.Y > TargetCell.Y) & (_Board[PlayerCell.X, PlayerCell.Y - max] != null) && _Board[PlayerCell.X, PlayerCell.Y-max].Type != CellType.Impassable) return _Board[PlayerCell.X, PlayerCell.Y - delta]; else if ((PlayerCell.Y < TargetCell.Y) & (_Board[PlayerCell.X, PlayerCell.Y + max] != null) && _Board[PlayerCell.X, PlayerCell.Y+max].Type != CellType.Impassable) return _Board[PlayerCell.X, PlayerCell.Y + delta]; } if (deltaX > max & deltaY > max) { delta = deltaX - max; newDelta = deltaY - max; if ((PlayerCell.X > TargetCell.X) && (PlayerCell.Y > TargetCell.Y) && (_Board[PlayerCell.X - max, PlayerCell.Y - max] != null) && _Board[PlayerCell.X - max, PlayerCell.Y-max].Type != CellType.Impassable) return _Board[PlayerCell.X - delta, PlayerCell.Y - newDelta]; else if ((PlayerCell.X > TargetCell.X) && (PlayerCell.Y < TargetCell.Y) && (_Board[PlayerCell.X - max, PlayerCell.Y + max] != null) && _Board[PlayerCell.X - max, PlayerCell.Y + max].Type != CellType.Impassable) return _Board[PlayerCell.X - delta, PlayerCell.Y + newDelta]; else if ((PlayerCell.X < TargetCell.X) && (PlayerCell.Y > TargetCell.Y) && (_Board[PlayerCell.X + max, PlayerCell.Y - max] != null) && _Board[PlayerCell.X + max, PlayerCell.Y - max].Type != CellType.Impassable) return _Board[PlayerCell.X + delta, PlayerCell.Y - newDelta]; else if ((PlayerCell.X < TargetCell.X) && (PlayerCell.Y < TargetCell.Y) && (_Board[PlayerCell.X + max, PlayerCell.Y + max] != null) && _Board[PlayerCell.X + max, PlayerCell.Y + max].Type != CellType.Impassable) return _Board[PlayerCell.X + delta, PlayerCell.Y + newDelta]; } --max; } return null; }
/// <summary>Применить магию</summary> private void ExecuteMagic(Cell target) { //Нет цели выходим if (_TargetBuilding == null && _TargetPlayer == null) return; Cell centerTarget=GetTargetCenter(); if (centerTarget == null) centerTarget = target; int di = _Players[0].Position.i; int dj = _Players[0].Position.j; var dx = Math.Abs(di-centerTarget.i); var dy = Math.Abs(dj-centerTarget.j); int max = _SelectedMagic.Radius / (Helper.ScreenWidth / _BoardWidth); if (dx > max+1 || dy > max+1) { if (!_Wait) { _Players[0].MoveTo(GetNearestCell(centerTarget)); _Wait = true; _LastTagret = centerTarget; } } else { _Players[0].Stop(); if (_SelectedMagic.Direction==DirectionType.fromHero) _SelectedMagic.Execute(_Players[0].Position, centerTarget); else _SelectedMagic.Execute(centerTarget, centerTarget); _Wait = false; _LastTagret = null; } }
/// <summary>Двигаемся вверх по прямой</summary> private void MoveTop() { _CurrentState.Y = _CurrentState.Y - _Speed; _Tile.UpdateInRange(_Animation.Top.Start, _Animation.Top.Stop); if (IsOver) { _Current = _Target; if (!MoveNext()) { _Target = null; _Tile.CurrentFrame = _Animation.Top.State; } } }
/// <summary>Двигает персонажа в клетку target</summary> /// <param name="target">Пункт назначения</param> public void MoveTo(Cell target) { if (target == null) return; _Target = target; }
/// <summary>Двигаемся вперед по прямой</summary> private void MoveForward() { _CurrentState.X = _CurrentState.X + _Speed; _Tile.UpdateInRange(_Animation.Forward.Start, _Animation.Forward.Stop); if (IsOver) { _Current = _Target; if (!MoveNext()) { _Target = null; _Tile.CurrentFrame = _Animation.Forward.State; } } }
/// <summary>Идем в следующую клетку по маршруту</summary> /// <returns></returns> private bool MoveNext() { if (_Route == null) return false; ++_CurrentPosition; if (_CurrentPosition < 0 || _CurrentPosition >= _Route.Count) { IsEnd = true; return false; } _Target = Helper.Board[_Route[_CurrentPosition].X, _Route[_CurrentPosition].Y]; return true; }
/// <summary>Обновляемся</summary> public void Update() { if (_Target == null) return; if (_Current != _Target) { if (_Delay != 0) { _Delay--; return; } else _Delay = 1; if ((_Current.j == _Target.j) && (_Target.i > _Current.i)) MoveForward(); else if (((_Current.j == _Target.j) && (_Target.i < _Current.i))) MoveBackward(); else if ((_Current.i == _Target.i) && (_Target.j < _Current.j)) MoveTop(); else if ((_Current.i == _Target.i) && (_Target.j > _Current.j)) MoveBottom(); else if ((_Current.i > _Target.i) && (_Target.j < _Current.j)) MoveTopLeft(); else if ((_Current.i < _Target.i) && (_Target.j < _Current.j)) MoveTopRight(); else if ((_Current.i < _Target.i) && (_Target.j > _Current.j)) MoveBottomRight(); else if ((_Current.i > _Target.i) && (_Target.j > _Current.j)) MoveBottomLeft(); } else { _Target = null; } }
public void Stop() { _Target = null; }
/// <summary>Двигаемся по маршруту от клетки к клетке</summary> /// <param name="route">Маршрут</param> public void MoveToRoute(List<Point> route) { _Route = route; _Target = Helper.Board[route[1].X, route[1].Y]; _CurrentPosition = 1; }
public void MoveTo(Cell to) { _Movement.Move(_CurrentCell,to,_CurrentState); }
/// <summary>Двигаемся вверх-вправо по диагонали</summary> private void MoveTopRight() { if (_CurrentState.Y != _Target.Rect.Y) _CurrentState.Y = _CurrentState.Y - _Speed; if (_CurrentState.X != _Target.Rect.X) _CurrentState.X = _CurrentState.X + _Speed; _Tile.UpdateInRange(_Animation.TopRight.Start, _Animation.TopRight.Stop); if (IsOver) { _Current = _Target; if (!MoveNext()) { _Target = null; _Tile.CurrentFrame = _Animation.TopRight.State; } } }
/// <summary>Применить магию</summary> /// <param name="From">От ячейки.</param> /// <param name="To">В ячейку.</param> public void Execute(Cell From, Cell To) { _Executed = true; _FromCell = From; _ToCell = To; Finished = false; }
public void Move(Cell from,Cell to,Rectangle state) { _Current = from; _CurrentState = state; Solver<PathNode, Object> aStar = new Solver<PathNode, Object>(_Field); _Route = new List<Point>(); var cell = from; var start = new Point(cell.i, cell.j); var finish = new Point(to.i, to.j); IEnumerable<PathNode> path = aStar.Search(start, finish, null); if (path != null) { foreach (PathNode node in path) _Route.Add(new Point(node.i, node.j)); MoveToRoute(_Route); IsEnd = false; } else IsEnd = true; }