internal override void Strike(Character owner, Character target) { // после выстрела можно запускать таймер блокировки выстрелов (реализация скорострельности) // может быть это не тот уровень, на котором нужно учитывать скорострельность, // может её надо учитывать на стадии "button1_Click"? target.Health -= (byte)((owner.DamagePerSecond + base.DamagePerSecond) / base.StrikesPerSecond); }
/// <summary> /// Вызывается, когда игра отрисовывается. /// </summary> /// <param name="gameTime">Предоставляет моментальный снимок значений времени.</param> public void Draw(GameTime gameTime, SpriteBatch spriteBatch, Character character) { spriteBatch.Draw(textureImage, character.Position, new Rectangle(currentFrame.X * frameSize.X, currentFrame.Y * frameSize.Y, frameSize.X, frameSize.Y), Color.White, 0, Vector2.Zero, 1f, SpriteEffects.None, 0); }
public void Relocate(Character character) { Point oldZone = GetZone(character.Position); Point newZone = GetZone(character.MoveBehavior.NewPosition); if (newZone.X != oldZone.X || newZone.Y != oldZone.Y) { Characters[oldZone.X][oldZone.Y].Remove(character); Characters[newZone.X][newZone.Y].Add(character); } }
public Point GetPositionOnGrid(Character character) { int newZoneX = (int)Math.Floor(character.Position.X / _tileSize); int newZoneY = (int)Math.Floor(character.Position.Y / _tileSize); return new Point(newZoneX, newZoneY); }
public MonsterMoveAStar(Character character, Level level, params Character[] targets) : base(character, targets) { _grid = GetSimplifiedGrid(level); _AStar = new AStar(); }
public void Fight(Character enemy) { Weapon.Strike(this, enemy); }
public NetPlayer(IMessenger messenger, Character character) { this.Messenger = messenger; this.Character = character; ClientPacket.PlayerId = (byte)character.Id; }
private bool CheckVoxel(Character shooter, float shootingTime, Vector2 direction, Point voxel) { bool result = false; // проверяем попадания в объекты // зона попадания Rectangle hitArea = new Rectangle(voxel.X * Level.ZoneSize, voxel.Y * Level.ZoneSize, (voxel.X + 1) * Level.ZoneSize, (voxel.Y + 1) * Level.ZoneSize); foreach (var solid in _gameState.Grid.Solids[voxel.X][voxel.Y]) { Vector2 hitPos = GetHitPosition(direction, shooter, solid); if (hitPos.X != -1) { if (hitPos.X < shooter.Position.X && hitPos.X > hitArea.X) { hitArea.X = (int)hitPos.X; result = true; } if (hitPos.X > shooter.Position.X && hitPos.X < hitArea.Width) { hitArea.Width = (int)hitPos.X; result = true; } if (hitPos.Y < shooter.Position.Y && hitPos.Y > hitArea.Y) { hitArea.Y = (int)hitPos.Y; result = true; } if (hitPos.Y > shooter.Position.Y && hitPos.Y < hitArea.Height) { hitArea.Height = (int)hitPos.Y; result = true; } } } // проверяем попадания в игроков Character[] playersInVoxel = _gameState.Grid.Characters[voxel.X][voxel.Y].ToArray(); foreach (var player in playersInVoxel) { if (player != shooter) { if (((player.Position.X >= shooter.Position.X && player.Position.X <= hitArea.Width) || (player.Position.X <= shooter.Position.X && player.Position.X >= hitArea.X)) && ((player.Position.Y >= shooter.Position.Y && player.Position.Y <= hitArea.Height) || (player.Position.Y <= shooter.Position.Y && player.Position.Y >= hitArea.Y))) { Vector2 hitPos = GetHitPosition(direction, shooter, player); if (hitPos.X != -1) { ApplyHit(shooter, player, shootingTime); } } } } return result; }
public void RemoveTarget(Character target) { Targets.Remove(target); }
public void AddTarget(Character target) { Targets.Add(target); }
public StupidMonsterMove(Character character, params Character[] targets) { Character = character; Targets = new List<Character>(targets); }
internal abstract void Strike(Character owner, Character target);
private void DeepCorrection(Character character, Solid solid) { Vector2 newPos = character.MoveBehavior.NewPosition; float charRectLeft = newPos.X - (character.CollisionOffset.X >> 1); float charRectTop = newPos.Y - (character.CollisionOffset.Y >> 1); float charRectRight = newPos.X + (character.CollisionOffset.X >> 1); float charRectBottom = newPos.Y + (character.CollisionOffset.Y >> 1); Vector2 minDelta = Vector2.Zero; float minDeltaLength = 0; Vector2[] axes = new Vector2[solid.Axes.Length + 2]; axes[0] = new Vector2(1, 0); axes[1] = new Vector2(0, 1); solid.Axes.CopyTo(axes, 2); foreach (var axis in axes) { // проекция персонажа Vector2 projBegin1; projBegin1 = GetProjection(new Vector2(charRectLeft, charRectTop), axis); Vector2 proj = GetProjection(new Vector2(charRectLeft, charRectBottom), axis); if ((proj.X < projBegin1.X) || ((proj.X == projBegin1.X) && (proj.Y < projBegin1.Y))) projBegin1 = proj; Vector2 projEnd1; projEnd1 = GetProjection(new Vector2(charRectRight, charRectTop), axis); proj = GetProjection(new Vector2(charRectRight, charRectBottom), axis); if ((proj.X > projEnd1.X) || ((proj.X == projEnd1.X) && (proj.Y > projEnd1.Y))) projEnd1 = proj; // проекция тела Vector2 projBegin2; Vector2 projEnd2; projBegin2 = projEnd2 = GetProjection(solid.Vertices[0], axis); for (int i = 1; i < solid.Vertices.Length; i++) { proj = GetProjection(solid.Vertices[i], axis); if ((proj.X < projBegin2.X) || ((proj.X == projBegin2.X) && (proj.Y < projBegin2.Y))) projBegin2 = proj; else if ((proj.X > projEnd2.X) || ((proj.X == projEnd2.X) && (proj.Y > projEnd2.Y))) projEnd2 = proj; } Vector2 delta = Vector2.Zero; Vector2 d1 = projEnd1 - projBegin2; if ((d1.X > 0) || ((d1.X == 0) && (d1.Y > 0))) { Vector2 d2 = projEnd2 - projBegin1; if ((d2.X > 0) || ((d2.X == 0) && (d2.Y > 0))) { if ((d1.X < d2.X) || ((d1.X == d2.X) && (d1.Y <= d2.Y))) { delta = -d1; } else { delta = d2; } } } if (delta == Vector2.Zero) { return; } float deltaLength = delta.Length(); if ((minDelta == Vector2.Zero) || (deltaLength < minDeltaLength)) { minDelta = delta; minDeltaLength = deltaLength; } } character.MoveBehavior.NewPosition += minDelta; }
public NetPlayer(IMessenger messenger, Character character, TimeSpan createTime) : this(messenger, character) { LastUpdate = createTime; }
private void ApplyHit(Character shooter, Character player, float shootingTime) { player.Health -= shootingTime * shooter.DamagePerSecond; if (player.Health <= 0) { // добавляем игрока в точку респауна зону и удаляем с зоны, в которой он был int x = (int)Math.Floor(player.Position.X / Level.ZoneSize); int y = (int)Math.Floor(player.Position.Y / Level.ZoneSize); _gameState.Grid.Characters[x][y].Remove(player); player.Position = _gameState.Level.GetRespawnPosition(); int newX = (int)Math.Floor(player.Position.X / Level.ZoneSize); int newY = (int)Math.Floor(player.Position.Y / Level.ZoneSize); _gameState.Grid.Characters[newX][newY].Add(player); player.Health = Character.MaxHealth; _gameState.Scores[shooter.Id].Kills++; _gameState.Scores[player.Id].Deaths++; foreach (var netPlayer in _gameState.NetPlayers.Values) { netPlayer.ServerPacket.PlayersPositions[player.Id] = (ProtoVector2)player.Position; netPlayer.ServerPacket.PlayersHealths[(byte)player.Id] = (byte)player.Health; } } else { foreach (var netPlayer in _gameState.NetPlayers.Values) { netPlayer.ServerPacket.PlayersHealths[(byte)player.Id] = (byte)player.Health; } } }
private void CheckHits(Character shooter, Vector2 direction, float shootingTime) { int voxelSize = Level.ZoneSize; // координаты ячейки, в которой находится начало луча int X = (int)Math.Floor(shooter.Position.X / voxelSize); int Y = (int)Math.Floor(shooter.Position.Y / voxelSize); // шаг по ячейкам в направлении луча int stepX = (direction.X > 0) ? 1 : -1; int stepY = (direction.Y > 0) ? 1 : -1; // расстояние вдоль луча до первой вертикальной линии, которую пересекает луч Vector2 horIntersection = GetIntersectionPosition(shooter.Position, direction, new Vector2((X + (stepX > 0 ? 1 : 0)) * voxelSize, 0), new Vector2(0, 1)) - shooter.Position; float tMaxX = horIntersection.Length(); // расстояние вдоль луча до первой горизонтальной линии, которую пересекает луч Vector2 verIntersection = GetIntersectionPosition(shooter.Position, direction, new Vector2(0, (Y + (stepY > 0 ? 1 : 0)) * voxelSize), new Vector2(1, 0)) - shooter.Position; float tMaxY = verIntersection.Length(); // расстояние вдоль луча, которое нужно пройти, чтобы заполнить ширину ячейки Vector2 fillWidth = GetIntersectionPosition(Vector2.Zero, direction, new Vector2(voxelSize, 0), new Vector2(0, 1)); float tDeltaX = fillWidth.Length(); // расстояние вдоль луча, которое нужно пройти, чтобы заполнить высоту ячейки Vector2 fillHeigth = GetIntersectionPosition(Vector2.Zero, direction, new Vector2(0, voxelSize), new Vector2(1, 0)); float tDeltaY = fillHeigth.Length(); // обоходим последовательно ячейки, которые пересекает луч while (true) { if (CheckVoxel(shooter, shootingTime, direction, new Point(X, Y))) { break; } if (tMaxX < tMaxY) { tMaxX += tDeltaX; X += stepX; if (X < 0 || X >= _gameState.Grid.Width) { break; } } else { tMaxY += tDeltaY; Y += stepY; if (Y < 0 || Y >= _gameState.Grid.Height) { break; } } } }
public void Put(Character character) { int x = (int)Math.Floor(character.Position.X / Level.ZoneSize); int y = (int)Math.Floor(character.Position.Y / Level.ZoneSize); Characters[x][y].Add(character); }
/// <summary> /// Возвращает точку пересечения луча с объектом. /// </summary> /// <param name="angle"></param> /// <param name="koef"></param> /// <param name="shooter"></param> /// <param name="target"></param> /// <returns></returns> private Vector2 GetHitPosition(Vector2 direction, Character shooter, ISolid target) { Vector2 hitPosition = new Vector2(-1); Vector2 p0 = shooter.Position; float minX = float.PositiveInfinity; float minY = float.PositiveInfinity; // пересечение с отрезками полигона Vector2[] vertices = target.Vertices; Vector2 prevV = vertices[vertices.Length - 1]; for (int i = 0; i < vertices.Length; i++) { Vector2 curV = vertices[i]; Vector2 intr = GetIntersectionPosition(shooter.Position, direction, curV, curV - prevV); float x = intr.X; float y = intr.Y; // точка пересечения прямых в пределах отрезка if (((x >= prevV.X) && (x < curV.X)) || ((x >= curV.X) && (x < prevV.X)) || ((y >= prevV.Y) && (y < curV.Y)) || ((y >= curV.Y) && (y < prevV.Y))) { // точка пересечения в направлении стрельбы Vector2 delta = new Vector2(x - p0.X, y - p0.Y); if (((delta.X >= 0 && direction.X >= 0) || (delta.X < 0 && direction.X < 0)) && ((delta.Y >= 0 && direction.Y >= 0) || (delta.Y < 0 && direction.Y < 0))) { if (delta.X != 0) { float positiveDeltaX = Math.Abs(delta.X); if (positiveDeltaX < minX) { minX = positiveDeltaX; hitPosition = new Vector2((float)x, (float)y); } } else { float positiveDeltaY = Math.Abs(delta.Y); if (positiveDeltaY < minY) { minY = positiveDeltaY; hitPosition = new Vector2((float)x, (float)y); } } } } prevV = curV; } return hitPosition; }
public PlayerMove1(Character character) { this._character = character; }