/// <summary> /// This method will create a projectile object or beam object /// </summary> /// <param name="cc"></param> /// <param name="tank"></param> private void ProjectileCreation(ControlCommand cc, Tank tank) { //figure out what kind of weapon String fireStatus = cc.GetFire(); //Get aim direction Vector2D turretDirection = cc.GetTurretDirection(); if (fireStatus == "main")// Normal attack { //Check fire cooldown if (!tank.HasFired) { //Create the new projectile in a thread safe manner lock (serverWorld.Projectiles) { Projectile proj = new Projectile(tank.GetID(), tank.Location, turretDirection, tank.GetID()); //Tank has fired so begin cooldown tank.HasFired = true; serverWorld.Projectiles[proj.getID()] = proj; } } } //This is a beam attack else if (fireStatus == "alt") { //Check if a tank has picked up a powerup if (tank.PowerUpNumber > 0) { //Create a new beam Beam beam = new Beam(tank.Location, turretDirection, tank.GetID(), tank.GetID()); //Decrement tanks powerup number tank.UsePowerup(); //Add beam to world to send message to clients lock (serverWorld.Beams) { serverWorld.Beams.Add(beam.GetID(), beam); } //Check if the beam kills any tanks lock (serverWorld.Tanks) { foreach (Tank t in serverWorld.Tanks.Values) { if (Intersects(beam.Origin, beam.Direction, t.Location, 30)) { t.HealthLevel = 0; t.HasDied = true; //increment player score serverWorld.Tanks[beam.GetOwner()].Score++; } } } } } }
/// <summary> /// Method will draw the turrets on top of the tanks /// </summary> /// <param name="o"></param> /// <param name="e"></param> private void TurretDrawer(object o, PaintEventArgs e) { //Extract tank from object so that we can assign turret color to correct tank Tank t = o as Tank; //Switch case here based on tank id int tankID = (t.GetID() % 8); // Get the tanks ID number and assign them a tank color based on that switch (tankID) { //blue turret case 0: e.Graphics.DrawImage(blueTurret, -25, -25, 50, 50); break; //Dark turret case 1: e.Graphics.DrawImage(darkTurret, -25, -25, 50, 50); break; //Green turret case 2: e.Graphics.DrawImage(greenTurret, -25, -25, 50, 50); break; //Light Green turret case 3: e.Graphics.DrawImage(lgTurret, -25, -25, 50, 50); break; //Orange turret case 4: e.Graphics.DrawImage(orangeTurret, -25, -25, 50, 50); break; //Purple turret case 5: e.Graphics.DrawImage(purpleTurret, -25, -25, 50, 50); break; //Red turret case 6: e.Graphics.DrawImage(redTurret, -25, -25, 50, 50); break; //Yellow turret case 7: e.Graphics.DrawImage(yellowTurret, -25, -25, 50, 50); break; } }
/// <summary> /// This method draws the tank to the client /// </summary> /// <param name="o"></param> /// <param name="e"></param> private void DrawTank(object o, PaintEventArgs e) { Tank t = o as Tank; //Switch case here int tankID = (t.GetID() % 8); // Get the tanks ID number and assign them a tank color based on that switch (tankID) { //blue tank case 0: e.Graphics.DrawImage(blueTank, -30, -30, 60, 60); break; //dark tank case 1: e.Graphics.DrawImage(darkTank, -30, -30, 60, 60); break; //green tank case 2: e.Graphics.DrawImage(greenTank, -30, -30, 60, 60); break; //light green tank case 3: e.Graphics.DrawImage(lightGreenTank, -30, -30, 60, 60); break; //orange tank case 4: e.Graphics.DrawImage(orangeTank, -30, -30, 60, 60); break; //purple tank case 5: e.Graphics.DrawImage(purpleTank, -30, -30, 60, 60); break; //red tank case 6: e.Graphics.DrawImage(redTank, -30, -30, 60, 60); break; //yellow tank case 7: e.Graphics.DrawImage(yellowTank, -30, -30, 60, 60); break; } }
/// <summary> /// This method handles the respawn of tank players when they have died /// </summary> /// <param name="player"></param> private void RespawnPlayer(Tank player) { //Do not do anything if player is not connected if (player.HasDisconnected) { return; } //Get a new location for the tank serverWorld.Tanks[player.GetID()].Location = RandomLocationGenerator(); //Avoid spawning on objects while (CheckForCollision(player, 1)) { serverWorld.Tanks[player.GetID()].Location = RandomLocationGenerator(); } //Reset stats of tank player.HealthLevel = 3; player.HasDied = false; //Reset frame timer for respawn player.WaitRespawn = 0; }
/// <summary> /// The method takes the current JsonMessage from ProcessMessage and /// updates the models within the world. /// </summary> /// <param name="JsonMessage">Message passed from ProccessMessage</param> /// <param name="objectType">Int number representing the object's type</param> private void UpdateWorldModel(string JsonMessage, int objectType) { // Enter switch case based on what object has identified as and // update the models in the world switch (objectType) { case 0: // Convert Json message into Tank object Tank curTank = JsonConvert.DeserializeObject <Tank>(JsonMessage); //The tank object is us if (curTank.GetID() == playerID) { selfTank = curTank; } lock (theWorld.Tanks) { // Check if the world contains the object already if (theWorld.Tanks.ContainsKey(curTank.GetID())) { // Remove the tank so that it can be updated theWorld.Tanks.Remove(curTank.GetID()); } //Add the tank to the world theWorld.Tanks.Add(curTank.GetID(), curTank); } break; case 1: // Convert Json message into Wall object Wall curWall = JsonConvert.DeserializeObject <Wall>(JsonMessage); // No check needed to see if it already exists since walls will only be added once // Add the wall into the world lock (theWorld.Walls) { theWorld.Walls.Add(curWall.GetID(), curWall); } break; case 2: // Convert Json message into Projectile object Projectile curProjectile = JsonConvert.DeserializeObject <Projectile>(JsonMessage); // Check if the world contains the object already lock (theWorld.Projectiles) { if (theWorld.Projectiles.ContainsKey(curProjectile.getID())) { // Remove the projectile so that it can be updated theWorld.Projectiles.Remove(curProjectile.getID()); } //Check if projectile is still active if (!curProjectile.Died) { // Re-add the projectile back into the world theWorld.Projectiles.Add(curProjectile.getID(), curProjectile); } } break; case 3: // Convert Json message into PowerUp object PowerUp curpowerUp = JsonConvert.DeserializeObject <PowerUp>(JsonMessage); // Check if the world contains the object already lock (theWorld.PowerUps) { if (theWorld.PowerUps.ContainsKey(curpowerUp.getID())) { // Remove the PowerUp so that it can be updated theWorld.PowerUps.Remove(curpowerUp.getID()); } //Check if the powerup was collected or not if (!curpowerUp.collected) { // Re-add the PowerUp back into the world theWorld.PowerUps.Add(curpowerUp.getID(), curpowerUp); } } break; case 4: // Convert Json message into Beam object Beam curBeam = JsonConvert.DeserializeObject <Beam>(JsonMessage); // Check if the world contains the object already lock (theWorld.Beams) { // add the Beam into the world theWorld.Beams.Add(curBeam.GetID(), curBeam); //Trigger a timer with the beam so that it is removed from the world after a certain time beamTimer = new Timer(new TimerCallback(RemoveBeam), curBeam, 500, -1); } break; } UpdateWorld(); }
/// <summary> /// We will receive the player's name and assign an ID number /// At this time we will also send to the client world size, the ID number /// and the walls /// </summary> /// <param name="client"></param> private void GetPlayerInfo(SocketState client) { //Check if error occured and write message to console if (client.ErrorOccured) { Console.WriteLine(client.ErrorMessage); } //Set the new callback action client.OnNetworkAction = GetActionDataFromClient; //Get the player name string playerName = client.GetData().Trim('\n'); //Create a new tank representing the player at a random location Tank newPlayer = new Tank(playerNumber, playerName, RandomLocationGenerator()) { //Allows the tank to fire upon spawn FrameCount = framesBetweenShot + 1 }; //We don't spawn on walls or powerups while (CheckForCollision(newPlayer, 1)) { newPlayer.Location = new Vector2D(RandomLocationGenerator()); } //Add player to our connections lock (connections) { //Send ID and worldsize info Networking.Send(client.TheSocket, playerNumber.ToString() + "\n" + serverWorld.Size.ToString() + "\n"); //Add socket state to the collection of players with their ID number connections.Add(client, playerNumber); } Console.WriteLine("Player " + playerNumber.ToString() + ": " + playerName + " has connected."); //Add player to server world lock (serverWorld.Tanks) { serverWorld.Tanks.Add(newPlayer.GetID(), newPlayer); //Increase player ID number playerNumber++; } //Create a string builder info to serialize and send all the walls StringBuilder wallinfo = new StringBuilder(); foreach (Wall wall in serverWorld.Walls.Values) { wallinfo.Append(JsonConvert.SerializeObject(wall) + "\n"); } //Send walls to the client Networking.Send(client.TheSocket, wallinfo.ToString()); //Empty the socket state of data client.ClearData(); //Begin receive loop Networking.GetData(client); }
/// <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> /// 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(); }