public void Update(float dt) { // Update resources. for (int i = 0; i < resources.GetLength(0); i++) { for (int j = 0; j < resources.GetLength(1); j++) { resources[j, i].Update(dt); // Update colony productions. if (resources[j, i].isAColony()) { resources[j, i].EvaluateProduction(ships, hexes[j, i]); } // Validate workable tiles. ValidateAdjacentTiles(new Vector2(i, j), false); // Assign influence hexes. if (!resources[j, i].GetHasInfluence()) { // Influence not assigned; must assign. ownedHexes.Add(new HexCell(hexes[j, i].GetPos() + new Vector3(0, (int)(lenSide * -0.01), 0), (int)(lenSide * 1.01), hexes[j, i].GetCoordinates())); resources[j, i].ChangeInfluence(true); } } } for (int i = 0; i < ships.Count; i++) { if (ships[i].active) { ships[i].Update(dt); } } // Update influence hexes. for (int i = 0; i < ownedHexes.Count; i++) { ownedHexes[i].Update(dt, resources[(int)ownedHexes[i].GetCoordinates().Y, (int)ownedHexes[i].GetCoordinates().X].workers); } // Pulsate selection and hover hexes. selectionHex.Update(dt, 0.0f); hoverHex.Update(dt, 0.0f); // Update AI. basicAI.Update(dt); // See if AI can create a new ship. if (basicAI.newShipInterval <= 0.0f) { // Make sure spawning hex is empty. if (!hexes[height - 1, width - 1].hasShip) { ScoutShip newAIShip = new ScoutShip((int)Global.PlayerOwners.Computer1, hexes[height - 1, width - 1]); ships.Add(newAIShip); basicAI.AddAI(ships[ships.IndexOf(newAIShip)]); // Just to not make me dumb from thinking pointers aren't the same in other programming languages. } } // See if AI can give orders to any ships. for (int i = 0; i < basicAI.orderIntervals.Count; i++) { BaseShip AISelectedShip = basicAI.AIShips[i]; if (basicAI.orderIntervals[i] <= 0.0f) { // An order is up. int theOrder = basicAI.OrderShip(i); Vector2 orderDestination = AISelectedShip.hexCell.GetCoordinates(); bool oddRow = AISelectedShip.hexCell.GetCoordinates().Y % 2 > 0 ? true : false; if (oddRow) { switch (theOrder) { case 0: // TopRight exit orderDestination.X += 1.0f; orderDestination.Y += 1.0f; break; case 1: // Right exit orderDestination.X += 1.0f; break; case 2: // BottomRight exit orderDestination.X += 1.0f; orderDestination.Y -= 1.0f; break; case 3: // BottomLeft exit orderDestination.Y -= 1.0f; break; case 4: // Left exit orderDestination.X -= 1.0f; break; case 5: // TopLeft exit orderDestination.Y += 1.0f; break; } } if (!oddRow) { switch (theOrder) { case 0: // TopRight exit orderDestination.Y += 1.0f; break; case 1: // Right exit orderDestination.X += 1.0f; break; case 2: // BottomRight exit orderDestination.Y -= 1.0f; break; case 3: // BottomLeft exit orderDestination.Y -= 1.0f; orderDestination.X -= 1.0f; break; case 4: // Left exit orderDestination.X -= 1.0f; break; case 5: // TopLeft exit orderDestination.Y += 1.0f; orderDestination.X -= 1.0f; break; } } // Ensure the destination is valid. if ((orderDestination.X > 0 && orderDestination.X < Global.Instance.HexGridSizeX) && (orderDestination.Y > 0 && orderDestination.Y < Global.Instance.HexGridSizeY)) { bool combatKilledMe = false; // Check for combat (instant). for (int j = 0; j < ships.Count; j++) { if (ships[j].owner == (int)Global.PlayerOwners.User) { if (ships[j].hexCell.GetCoordinates() == orderDestination) { combatKilledMe = Combat(AISelectedShip, ships[j]); } } } // Don't continue if player defended successfully against attack. if (combatKilledMe) { } else { // Set course. AISelectedShip.SetDestination(hexes[(int)orderDestination.Y, (int)orderDestination.X], hexes); } } else { // Order is ignored and skipped as it is invalid. } } } }
public MapManager(int width, int height, int a_lenSide, int xOffset, int yOffset, GraphicsDevice device) { this.gridVerts = new List <VertexPositionColor>(); this.ships = new List <BaseShip>(); this.ownedHexes = new List <HexCell>(); this.resourceVerts = new List <VertexPositionColor>(); this.width = width; this.height = height; this.xOffset = xOffset; this.yOffset = yOffset; this.lenSide = a_lenSide; hexes = new HexCell[height, width]; resources = new ResourceObject[height, width]; basicAI = new BasicAI(); effect = new BasicEffect(device, null); effect.VertexColorEnabled = true; float h = Global.Instance.CalculateH(lenSide); float r = Global.Instance.CalculateR(lenSide); float hexWidth = 0; float hexHeight = 0; hexWidth = r + r; hexHeight = lenSide + h; this.pixelWidth = (width * hexWidth) + r; this.pixelHeight = (height * hexHeight) + h; bool inTopRow = false; bool inBottomRow = false; bool inLeftColumn = false; bool inRightColumn = false; bool isTopLeft = false; bool isTopRight = false; bool isBottomLeft = false; bool isBottomRight = false; for (int i = 0; i < height; i++) { for (int j = 0; j < width; j++) { #region Position Booleans if (i == 0) { inTopRow = true; } else { inTopRow = false; } if (i == height - 1) { inBottomRow = true; } else { inBottomRow = false; } if (j == 0) { inLeftColumn = true; } else { inLeftColumn = false; } if (j == width - 1) { inRightColumn = true; } else { inRightColumn = false; } if (inTopRow && inLeftColumn) { isTopLeft = true; } else { isTopLeft = false; } if (inTopRow && inRightColumn) { isTopRight = true; } else { isTopRight = false; } if (inBottomRow && inLeftColumn) { isBottomLeft = true; } else { isBottomLeft = false; } if (inBottomRow && inRightColumn) { isBottomRight = true; } else { isBottomRight = false; } #endregion // Calculate hex positions. if (isTopLeft) { // First hex. hexes[0, 0] = new HexCell(new Vector3(0 + r + xOffset, 0 + yOffset, 0), lenSide, new Vector2(0, 0)); } else { if (inLeftColumn) { // Calculate from hex above and stagger the rows. if (i % 2 == 0) { hexes[i, j] = new HexCell(hexes[i - 1, j].vertices[(int)HexVertice.BottomLeft].Position, lenSide, new Vector2(j, i)); } else { hexes[i, j] = new HexCell(hexes[i - 1, j].vertices[(int)HexVertice.BottomRight].Position, lenSide, new Vector2(j, i)); } } else { // Calculate from hex to the left. float x = hexes[i, j - 1].vertices[(int)HexVertice.TopRight].Position.X; float y = hexes[i, j - 1].vertices[(int)HexVertice.TopRight].Position.Y; x += r; y -= h; hexes[i, j] = new HexCell(new Vector3(x, y, 0), lenSide, new Vector2(j, i)); } } } } selectionHex = new HexCell(hexes[0, 0].GetPos() + new Vector3(0, (int)(lenSide * 0.2), 0), (int)(lenSide * 0.8), new Vector2(0, 0)); hoverHex = new HexCell(hexes[0, 0].GetPos() + new Vector3(0, (int)(lenSide * 0.01), 0), (int)(lenSide * 0.99), new Vector2(0, 0)); // Combine each hex vertex list into grid vertex list. for (int i = 0; i < hexes.GetLength(0); i++) { for (int j = 0; j < hexes.GetLength(1); j++) { gridVerts.AddRange(hexes[i, j].vertices.ToArray()); } } // Load layer 1 (resources). // Assign resources to each hex location. for (int i = 0; i < height; i++) { for (int j = 0; j < width; j++) { resources[i, j] = new ResourceObject((int)Global.PlayerOwners.None, hexes[i, j], (int)Global.Instance.rand.Next(0, 4)); } } // Create some visually linear distributions of black holes to act as 'walls' for A*. int blackholeStreaks = (int)Global.Instance.rand.Next(7, 14); for (int i = 0; i < blackholeStreaks; i++) { Vector2 streakCoords = new Vector2(Global.Instance.rand.Next(1, Global.Instance.HexGridSizeX - 2), Global.Instance.rand.Next(1, Global.Instance.HexGridSizeY - 2)); int streakLength = (int)Global.Instance.rand.Next(9, 15); int streakDirection = 0; for (int j = 0; j < streakLength; j++) { resources[(int)streakCoords.Y, (int)streakCoords.X].resourceType = 9; hexes[(int)streakCoords.Y, (int)streakCoords.X].toggleHasShip(true); streakDirection = Global.Instance.rand.Next(0, 6); bool oddRow = streakCoords.Y % 2 > 0 ? true : false; Vector2 nextCoords = streakCoords; if (oddRow) { switch (streakDirection) { case 0: // TopRight exit nextCoords.X += 1.0f; nextCoords.Y += 1.0f; break; case 1: // Right exit nextCoords.X += 1.0f; break; case 2: // BottomRight exit nextCoords.X += 1.0f; nextCoords.Y -= 1.0f; break; case 3: // BottomLeft exit nextCoords.Y -= 1.0f; break; case 4: // Left exit nextCoords.X -= 1.0f; break; case 5: // TopLeft exit nextCoords.Y += 1.0f; break; } } else if (!oddRow) { switch (streakDirection) { case 0: // TopRight exit nextCoords.Y += 1.0f; break; case 1: // Right exit nextCoords.X += 1.0f; break; case 2: // BottomRight exit nextCoords.Y -= 1.0f; break; case 3: // BottomLeft exit nextCoords.Y -= 1.0f; nextCoords.X -= 1.0f; break; case 4: // Left exit nextCoords.X -= 1.0f; break; case 5: // TopLeft exit nextCoords.Y += 1.0f; nextCoords.X -= 1.0f; break; } } // Skip if it's a border tile. if ((nextCoords.X < 1 || nextCoords.X > Global.Instance.HexGridSizeX - 2) || (nextCoords.Y < 1 || nextCoords.Y > Global.Instance.HexGridSizeY - 2)) { // streakCoords remain the same. } else { streakCoords = nextCoords; } // This location becomes a black hole. (hasShip has an unfortunate name.) resources[(int)streakCoords.Y, (int)streakCoords.X].resourceType = 9; hexes[(int)streakCoords.Y, (int)streakCoords.X].toggleHasShip(true); } } // Load layer 2 (ships) // Player starts off with one colony ship. ColonyShip playerBeginningShip = new ColonyShip((int)Global.PlayerOwners.User, hexes[0, 0]); ships.Add(playerBeginningShip); hexes[0, 0].toggleHasShip(true); ships[0].selected = true; // Computer starts off with a scout. ScoutShip computerBeginningShip = new ScoutShip((int)Global.PlayerOwners.Computer1, hexes[height - 1, width - 1]); ships.Add(computerBeginningShip); basicAI.AddAI(ships[1]); hexes[height - 1, width - 1].toggleHasShip(true); }