/// <summary> /// Updates all tanks currently present in The World /// </summary> /// <param name="t"> the tank thats being updated </param> public void UpdateTank(Tank t) { Players[t.ID] = t; Tanks[t.ID] = t; }
private Projectile ShootProjectileFromTank(Tank tank) { Projectile newProjectile = new Projectile(random.Next(), tank.Location, tank.TurretDirection, false, tank.ID); return(newProjectile); }
private void UpdateTankBodyDirection(Tank tank, TankControlCommand command) { Vector2D movingDirection = tank.BodyDirection; tank.BodyDirection = ModifyMovingDirection(command.Moving, movingDirection); }
private bool TankIsReadyToRespawn(Tank tank) { return(framesSinceLastDeath[tank.ID] >= gameSettings.RespawnDelay); }
private Beam ShootBeamFromTank(Tank tank) { Beam newBeam = new Beam(random.Next(), tank.Location, tank.TurretDirection, tank.ID); return(newBeam); }
private void SetTankJustDied(Tank tank) { tank.Died = true; framesSinceLastDeath[tank.ID] = 0; }
private bool TankIsZeroHealth(Tank tank) { return(tank.HealthPoints <= 0); }
/// <summary> /// Process any buffered messages separated by '\n' /// Then inform the view /// </summary> /// <param name="state"></param> private void ReceiveWorld(SocketState state) { //Gets the data from the state and splits it by a new line string totalData = state.GetData(); string[] parts = Regex.Split(totalData, @"(?<=[\n])"); // Loop until we have processed all messages. // We may have received more than one. //Gets the player number, which should only be once int playerNumber = 0; havePlayerNum = int.TryParse(parts[0], out playerNumber); parts[0] = ""; if (playerNumber != 0) { playerNum = playerNumber; } //Gets the dimensions of the world that should only happen once int dim = 0; haveDimension = int.TryParse(parts[1], out dim); parts[1] = ""; if (dim != 0) { worldDimension = dim; world = new World(worldDimension); } //Iterates through all the data given by the server foreach (string p in parts) { // Ignore empty strings added by the regex splitter if (p.Length == 0) { continue; } // The regex splitter will include the last string even if it doesn't end with a '\n', // So we need to ignore it if this happens. if (p[p.Length - 1] != '\n') { break; } //Locks with a world so that we process information in a single thread lock (world) { //Parses the object with the JSON JObject jObject = JObject.Parse(p); //Converts the JSON object to a token based on the name of the string JToken projToken = jObject["proj"]; JToken beamToken = jObject["beam"]; JToken tankToken = jObject["tank"]; JToken wallToken = jObject["wall"]; JToken powerToken = jObject["power"]; //If the projToken is not null, i.e. if the JSON string passed was a projectile, then it goes in this condition if (projToken != null) { //Deserializes the string and converts it to a projectile Projectile proj = JsonConvert.DeserializeObject <Projectile>(p); //Adds the projectile to the world world.SetProjectile(proj.GetID(), proj); //If projectile is dead, removes the projectile from the world if (proj.GetDead() == true) { world.GetProjectile().Remove(proj.GetID()); } } //If the beamToken is not null, i.e. if the JSON string passed was a beam, then it goes in this condition if (beamToken != null) { //Deserializes the string and converts it to a beam Beams b = JsonConvert.DeserializeObject <Beams>(p); //Adds the beam in the world's beam dictionary world.SetBeams(b.GetBeamID(), b); } //If the tankToken is not null, i.e. if the JSON string passed was a tank, then it goes in this condition if (tankToken != null) { //Deserializes the string and converts it to a tank Tank t = JsonConvert.DeserializeObject <Tank>(p); //Sets the color of the tank based on the tank's ID t.SetColor(t.GetID()); //Adds the tank to the world's tank dictionary world.SetTanks(t.GetID(), t); //If the hitpoints of the tank are 0, then it remove it from the dictionary if (t.GetHitPoints() == 0) { world.GetTanks().Remove(t.GetID()); } //If the tank gets disconnected, then it remove it from the dictionary if (t.GetDisconnected()) { world.GetTanks().Remove(t.GetID()); } //If the tank is dead, then it remove it from the dictionary if (t.GetDead()) { world.GetTanks().Remove(t.GetID()); } } //If the wallToken is not null, i.e. if the JSON string passed was a wall, then it goes in this condition if (wallToken != null) { //Deserializes the string and converts it to a wall Wall w = JsonConvert.DeserializeObject <Wall>(p); //Adds the wall to the world's wall dictionary world.SetWalls(w.GetID(), w); } //If the powerToken is not null, i.e. if the JSON string passed was a powerup, then it goes in this condition if (powerToken != null) { //Deserializes the string and converts it to a powerup Powerups power = JsonConvert.DeserializeObject <Powerups>(p); //Adds the powerup to the world's powerup dictionary world.SetPowerups(power.GetID(), power); //If the powerup is dead, then it removes it from the dictionary if (power.GetDead()) { world.GetPowerups().Remove(power.GetID()); } } } // Then remove it from the SocketState's growable buffer state.RemoveData(0, p.Length); } if (UpdateArrived != null) { // inform the view to redraw UpdateArrived(); } //Inform the server Process(); }
/// <summary> /// Draws a projectile /// </summary> private void ProjectileDrawer(object o, PaintEventArgs e) { //Converts the object to a projectile Projectile p = o as Projectile; //Sets the width to 30 int width = 30; //Doesn't smoothen the projectile drawing e.Graphics.SmoothingMode = System.Drawing.Drawing2D.SmoothingMode.None; using (System.Drawing.SolidBrush blueBrush = new System.Drawing.SolidBrush(System.Drawing.Color.Blue)) using (System.Drawing.SolidBrush yellowBrush = new System.Drawing.SolidBrush(System.Drawing.Color.Yellow)) using (System.Drawing.SolidBrush darkBlueBrush = new System.Drawing.SolidBrush(System.Drawing.Color.DarkBlue)) using (System.Drawing.SolidBrush greenBrush = new System.Drawing.SolidBrush(System.Drawing.Color.Green)) using (System.Drawing.SolidBrush lightGreenBrush = new System.Drawing.SolidBrush(System.Drawing.Color.LightGreen)) using (System.Drawing.SolidBrush redBrush = new System.Drawing.SolidBrush(System.Drawing.Color.Red)) using (System.Drawing.SolidBrush orangeBrush = new System.Drawing.SolidBrush(System.Drawing.Color.Orange)) using (System.Drawing.SolidBrush purpleBrush = new System.Drawing.SolidBrush(System.Drawing.Color.Purple)) { //Centers the projectile Rectangle r = new Rectangle(-(width / 2), -(width / 2), width, width); Color c = new Color(); foreach (int id in world.GetTanks().Keys) { //Sets the color based on the tank's color Tank t = world.GetTanks()[id]; if (t.GetID() == p.GetOwnerID()) { c = t.GetColor(); } } //Draws the projectile based on what the tank's color is if (c == Color.Red) { e.Graphics.DrawImage(redShot, r); } else if (c == Color.Yellow) { e.Graphics.DrawImage(yellowShot, r); } else if (c == Color.Blue) { e.Graphics.DrawImage(blueShot, r); } else if (c == Color.DarkBlue) { e.Graphics.DrawImage(whiteShot, r); } else if (c == Color.Purple) { e.Graphics.DrawImage(purpleShot, r); } else if (c == Color.Orange) { e.Graphics.DrawImage(brownShot, r); } else if (c == Color.Green) { e.Graphics.DrawImage(greenShot, r); } else if (c == Color.LightGreen) { e.Graphics.DrawImage(greyShot, r); } } }
/// <summary> /// Draws the HP bar for the tank using tank's orientation to draw appropriately. /// </summary> /// <param name="o"> Object o as tank (which tank to draw)</param> /// <param name="e"></param> private void HPDrawer(object o, PaintEventArgs e) { Tank t = o as Tank; int width = 60; int height = 5; e.Graphics.SmoothingMode = System.Drawing.Drawing2D.SmoothingMode.AntiAlias; //Differnt colors for differnt amounts of hp using (System.Drawing.SolidBrush greenBrush = new System.Drawing.SolidBrush(System.Drawing.Color.Green)) using (System.Drawing.SolidBrush yellowBrush = new System.Drawing.SolidBrush(System.Drawing.Color.Yellow)) using (System.Drawing.SolidBrush redBrush = new System.Drawing.SolidBrush(System.Drawing.Color.Red)) { // Using Tank Orientation to position HP Bar. // We position the HP bar Above the tank. Point barLocation; Size barSize; Rectangle threeHp; Rectangle twoHp; Rectangle oneHp; // Vertical if (t.orientation.GetX() == 0) { barSize = new Size(width, height); if (t.orientation.GetY() == -1) { barLocation = new Point(-30, -50); // North } else { e.Graphics.RotateTransform(180); barLocation = new Point(-30, -50); // South } // Different Rectangle lengths for hp amount threeHp = new Rectangle(barLocation, barSize); twoHp = new Rectangle(barLocation, barSize); twoHp.Width = twoHp.Width - 20; oneHp = new Rectangle(barLocation, barSize); oneHp.Width = oneHp.Width - 40; } // Horizontal requires different adjustments to height and width. else { barSize = new Size(height, width); if (t.orientation.GetX() == -1 && t.orientation.GetY() == 0) { barLocation = new Point(35, -30); // West } else { e.Graphics.RotateTransform(180); barLocation = new Point(35, -30); // East } // For horizontal orientaion we adjust the rectangle's height threeHp = new Rectangle(barLocation, barSize); twoHp = new Rectangle(barLocation, barSize); twoHp.Height = twoHp.Height - 20; oneHp = new Rectangle(barLocation, barSize); oneHp.Height = oneHp.Height - 40; } // Fill accordingly if (t.hitPoints == 3) { e.Graphics.FillRectangle(greenBrush, threeHp); } if (t.hitPoints == 2) { e.Graphics.FillRectangle(yellowBrush, twoHp); } if (t.hitPoints == 1) { e.Graphics.FillRectangle(redBrush, oneHp); } } }
/// <summary> /// This method will convert string representaion of current Json object, and update the world model /// This method will not check for walls since walls will only be sent once and will be processed in TryInitializedDrawingPanel method /// </summary> /// <param name="s">string representation of Json object </param> private void ConvertAndUpdateWorld(string s) { JObject obj = JObject.Parse(s); if (obj.ContainsKey("tank")) { Tank tank = JsonConvert.DeserializeObject <Tank>(s); lock (TheWorld.Tanks) { if (tank.Disconnected) // Remove the tank from the world and Start Explosion animation { if (TheWorld.Tanks.ContainsKey(tank.ID)) { TheWorld.Tanks.Remove(tank.ID); } Explode(tank); } else if (tank.Died) // Start an explosion animation { Explode(tank); } else // add to the world { if (TheWorld.Tanks.ContainsKey(tank.ID)) { TheWorld.Tanks[tank.ID] = tank; } else { TheWorld.Tanks.Add(tank.ID, tank); } } } } else if (obj.ContainsKey("power")) { Powerup powerup = JsonConvert.DeserializeObject <Powerup>(s); lock (TheWorld.Powerups) { if (powerup.Died) //Remove power up from the world { if (TheWorld.Powerups.ContainsKey(powerup.ID)) { TheWorld.Powerups.Remove(powerup.ID); } } else // Add to the World model as usual { if (TheWorld.Powerups.ContainsKey(powerup.ID)) { TheWorld.Powerups[powerup.ID] = powerup; } else { TheWorld.Powerups.Add(powerup.ID, powerup); } } } } else if (obj.ContainsKey("proj")) { Projectile projectile = JsonConvert.DeserializeObject <Projectile>(s); lock (TheWorld.Projectiles) { if (projectile.Died) // Remove projectile in the world { if (TheWorld.Projectiles.ContainsKey(projectile.ID)) { TheWorld.Projectiles.Remove(projectile.ID); } } else // Add to the World model as usual { if (TheWorld.Projectiles.ContainsKey(projectile.ID)) { TheWorld.Projectiles[projectile.ID] = projectile; } else { TheWorld.Projectiles.Add(projectile.ID, projectile); } } } } else if (obj.ContainsKey("beam")) { Beam beam = JsonConvert.DeserializeObject <Beam>(s); //Inform the drawing panel to draw beam StartBeamAnimation(beam); } }
/// <summary> /// Process JSON string received from server and convert it to objects /// </summary> /// <param name="message"></param> private void ProcessMessage(string message) { string caseString = ""; if (message.Contains("tank")) { caseString = "tank"; } if (message.Contains("proj")) { caseString = "proj"; } if (message.Contains("wall")) { caseString = "wall"; } if (message.Contains("power")) { caseString = "power"; } if (message.Contains("beam")) { caseString = "beam"; } // add and remove the world, so need to lock lock (theWorld) { // capture objects sent by server and update the world accordingly switch (caseString) { case "tank": Tank rebuiltTank = JsonConvert.DeserializeObject <Tank>(message); if (theWorld.Tanks.ContainsKey(rebuiltTank.ID)) { // if the tank is disconnected, remove the tank from the world if (rebuiltTank.disconnected) { theWorld.Tanks.Remove(rebuiltTank.ID); } else { theWorld.Tanks[rebuiltTank.ID] = rebuiltTank; } } else { theWorld.Tanks.Add(rebuiltTank.ID, rebuiltTank); } break; case "proj": Projectile rebuiltProj = JsonConvert.DeserializeObject <Projectile>(message); if (!theWorld.Projectiles.ContainsKey(rebuiltProj.ID)) { theWorld.Projectiles.Add(rebuiltProj.ID, rebuiltProj); } else { if (rebuiltProj.died) { theWorld.Projectiles.Remove(rebuiltProj.ID); } else { theWorld.Projectiles[rebuiltProj.ID] = rebuiltProj; } } break; case "wall": Wall rebuiltWall = JsonConvert.DeserializeObject <Wall>(message); if (!theWorld.Walls.ContainsKey(rebuiltWall.ID)) { theWorld.Walls.Add(rebuiltWall.ID, rebuiltWall); } break; case "power": Powerup rebuiltPower = JsonConvert.DeserializeObject <Powerup>(message); if (!theWorld.Powerups.ContainsKey(rebuiltPower.ID)) { theWorld.Powerups.Add(rebuiltPower.ID, rebuiltPower); } else { if (rebuiltPower.died) { theWorld.Powerups.Remove(rebuiltPower.ID); } else { theWorld.Powerups[rebuiltPower.ID] = rebuiltPower; } } break; case "beam": Beam rebuiltBeam = JsonConvert.DeserializeObject <Beam>(message); control.Fire = "none"; // Reset firing to prevent multiple beams in one frame if (!theWorld.Beams.ContainsKey(rebuiltBeam.ID)) { theWorld.Beams.Add(rebuiltBeam.ID, rebuiltBeam); } else { theWorld.Beams[rebuiltBeam.ID] = rebuiltBeam; } break; } } }
/// <summary> /// Deserializes an object from an inputted string. This is handled differently depending on which /// kind of object it is. /// </summary> /// <param name="serializedObject">Serialized object string</param> private void UpdateObject(string serializedObject) { JObject obj = JObject.Parse(serializedObject); //Tank JToken token = obj["tank"]; if (token != null) { Tank tank = JsonConvert.DeserializeObject <Tank>(serializedObject); TheWorld.Tanks[tank.ID] = tank; //Assigns a color to the tank and increments the seen players if (!TankColorRecord.ContainsKey(tank.ID)) { TankColorRecord.Add(tank.ID, SeenPlayers % 8); SeenPlayers++; } //If it disconnected the tank is removed if (tank.Disconnected) { TheWorld.Tanks.Remove(tank.ID); } //It also notes that the walls must be done if it's importing a tank wallsDone = true; return; } //Projectile token = obj["proj"]; if (token != null) { Projectile proj = JsonConvert.DeserializeObject <Projectile>(serializedObject); TheWorld.Projectiles[proj.ID] = proj; //Removes projectiles when they die if (proj.Died) { TheWorld.Projectiles.Remove(proj.ID); } return; } //Powerup token = obj["power"]; if (token != null) { PowerUp power = JsonConvert.DeserializeObject <PowerUp>(serializedObject); TheWorld.PowerUps[power.ID] = power; //Removes powerups when they die if (power.Died) { TheWorld.PowerUps.Remove(power.ID); } return; } //Beam token = obj["beam"]; if (token != null) { Beam beam = JsonConvert.DeserializeObject <Beam>(serializedObject); TheWorld.Beams[beam.ID] = beam; return; } //Wall token = obj["wall"]; if (token != null) { Wall wall = JsonConvert.DeserializeObject <Wall>(serializedObject); TheWorld.Walls[wall.ID] = wall; return; } }
public void DrawExplosion(Tank tank, PaintEventArgs e, int worldSize) { DrawingTransformer.DrawObjectWithTransform(e, tank, worldSize, tank.Location.GetX(), tank.Location.GetY(), 0, DrawExplosionSprite); }
/// <summary> /// Method for drawing the tanks /// </summary> /// <param name="o"></param> /// <param name="e"></param> private void TankDrawer(object o, PaintEventArgs e) { Tank t = o as Tank; //Stops tank from updating anymore information if health equals zero if (t.HitPoints == 0) { DrawExplosion(t, e); return; } //Resets the tank frames when the tank isn't dead else if (TheController.TheWorld.TankExplosions.ContainsKey(t.ID) && (TheController.TheWorld.TankExplosions[t.ID].tankFrames != 0 && !t.Died)) { TheController.TheWorld.ExplosionClearFrames(TheController.TheWorld.TankExplosions[t.ID]); } int tankWidth = Constants.TankSize; int tankHeight = Constants.TankSize; // Gets color ID of the tank int colorID = TheController.GetColor(t.ID); //Determines tank color based on the color ID of the tank switch (colorID) { //Blue case 0: e.Graphics.DrawImage(sourceImageBlueTank, -(tankWidth / 2), -(tankHeight / 2), tankWidth, tankHeight); break; //Dark case 1: e.Graphics.DrawImage(sourceImageDarkTank, -(tankWidth / 2), -(tankHeight / 2), tankWidth, tankHeight); break; //Green case 2: e.Graphics.DrawImage(sourceImageGreenTank, -(tankWidth / 2), -(tankHeight / 2), tankWidth, tankHeight); break; //Light Green case 3: e.Graphics.DrawImage(sourceImageLightGreenTank, -(tankWidth / 2), -(tankHeight / 2), tankWidth, tankHeight); break; //Orange case 4: e.Graphics.DrawImage(sourceImageOrangeTank, -(tankWidth / 2), -(tankHeight / 2), tankWidth, tankHeight); break; //Purple case 5: e.Graphics.DrawImage(sourceImagePurpleTank, -(tankWidth / 2), -(tankHeight / 2), tankWidth, tankHeight); break; //Red case 6: e.Graphics.DrawImage(sourceImageRedTank, -(tankWidth / 2), -(tankHeight / 2), tankWidth, tankHeight); break; //Yellow case 7: e.Graphics.DrawImage(sourceImageYellowTank, -(tankWidth / 2), -(tankHeight / 2), tankWidth, tankHeight); break; } }
static void Main(string[] args) { Tank ourTank = new Tank(5, 300, 20); SimpleComputerTank enemyTank = new SimpleComputerTank(10, 250, 10); bool isEnd = false; bool IsParsed = false; Actions ourAction = Actions.Shoot; Actions enmAction = Actions.Shoot; ShootResult shootResult; while (!isEnd) { Console.WriteLine("Новый ход!"); Console.WriteLine($"Наш танк. Жизни: {ourTank.Health} Количество патронов: {ourTank.RoundsNum}"); Console.WriteLine($"Танк противника. Жизни: {enemyTank.Health} Количество патронов: {enemyTank.RoundsNum}"); Console.WriteLine("Доступные действия: \n" + " 1. Выстрел\n" + " 2. Ремонт\n" + " 3. Покупка патронов\n" + "Введите число, соотвествующее желаемому действию:"); // Считывание действия пользователя с проверкой правильности ввода. string ioAction; do { ioAction = Console.ReadLine(); IsParsed = Enum.TryParse(ioAction, out ourAction); if (!IsParsed || (int)ourAction < 1 || (int)ourAction > 3) { Console.WriteLine("Введите допустимое число"); IsParsed = false; } }while (!IsParsed); Console.WriteLine(); // Наш ход. switch (ourAction) { case Actions.Shoot: Console.WriteLine("Наш танк стреляет!"); shootResult = ourTank.Shoot(enemyTank); switch (shootResult) { case ShootResult.Usual: Console.WriteLine("Противнику нанесён стандартный урон."); break; case ShootResult.Critical: Console.WriteLine("Критическое попадание! Танк нанёс на 20% больше урона."); break; case ShootResult.Miss: Console.WriteLine("Промах..."); break; case ShootResult.NoRounds: Console.WriteLine("Выстрелить не удалось. Купите патроны!"); break; } break; case Actions.Repair: ourTank.Repair(); Console.WriteLine("Наш танк починился!"); break; case Actions.Buy: ourTank.BuyRounds(); Console.WriteLine("Наш танк купил патроны!"); break; } // Наша победа. if (enemyTank.Health <= 0) { Console.WriteLine("Победа! Вражеский танк уничтожен!"); isEnd = true; } else { Console.WriteLine(); // Генерация действия противника. enmAction = enemyTank.ComputerTurn(ourTank); // Ход противника. switch (enmAction) { case Actions.Shoot: Console.WriteLine("Противник стреляет!"); shootResult = enemyTank.Shoot(ourTank); switch (shootResult) { case ShootResult.Usual: Console.WriteLine("Нам нанесён стандартный урон."); break; case ShootResult.Critical: Console.WriteLine("Критическое попадание! Противник нанёс на 20% больше урона."); break; case ShootResult.Miss: Console.WriteLine("Противник промахнулся..."); break; case ShootResult.NoRounds: Console.WriteLine("Противник не смог выстрелить, так как у него нет патронов."); break; } break; case Actions.Repair: enemyTank.Repair(); Console.WriteLine("Танк врага починился!"); break; case Actions.Buy: enemyTank.BuyRounds(); Console.WriteLine("Танк врага купил патроны!"); break; } // Победа противника. if (ourTank.Health <= 0) { Console.WriteLine("Поражение! Наш танк уничтожен!"); isEnd = true; } } // Отступ перед новым ходом. Console.WriteLine("\n"); } Console.WriteLine("Нажмите Enter, чтобы завершить работу программы..."); Console.ReadLine(); }