/// <summary> /// Creates and intialises all systems required for this game scene /// </summary> private void CreateSystems() { ISystem newSystem; // Creates the system to calculate the SkyBox newSystem = new SystemSkyBox(ref sceneManager.camera); systemManager.AddSystem(newSystem); // Creates an array of light point for use in SystemRenderer Vector3[] array = new Vector3[] { new Vector3(G1X, 13.0f, 10.0f), new Vector3(G2X, 13.0f, 10.0f) }; // Creates the system to calculate all the rendering (including lighting) newSystem = new SystemRender(ref sceneManager.camera, array); systemManager.AddSystem(newSystem); // Creates the system to handle all collision on X&Y axis (Sets object to check collision against to banana) ComponentPosition pos = (ComponentPosition)entityManager.FindEntity("Banana").FindComponent(ComponentTypes.COMPONENT_POSITION); newSystem = new SystemColliderXY(ref entityManager, pos); systemManager.AddSystem(newSystem); // Creates the system to handle the animation of game objects newSystem = new SystemAnimator(); systemManager.AddSystem(newSystem); }
/// <summary> /// Destroyes the terrain in a sphere shape emitting for provided entity /// </summary> /// <param name="entity">Entity to emit destruction from (entity hit by projectile)</param> private void DestroySkyline(string entity) { // Gets the entity name/id of the center building block int buildingID = int.Parse(entity.Substring(8, entity.Length - 8)); // Accesses that entities position component to get its value ComponentPosition pos = (ComponentPosition)entityManager.FindEntity(entity).FindComponent(ComponentTypes.COMPONENT_POSITION); // Uses the 2D array (SkylineLayout) and the position value the following will check for a building block ID // If the ID comes back as 0 then no entity is present there, anything else equals the block ID // The following checks for entities that exist for the orignal entity, above, below and either side of it int centerID = SkylineLayout[(int)(pos.Position.Y + 12), (int)(pos.Position.X + 27.5)]; int bottomID = SkylineLayout[(int)(pos.Position.Y + 11), (int)(pos.Position.X + 27.5)]; int topID = SkylineLayout[(int)(pos.Position.Y + 13), (int)(pos.Position.X + 27.5)]; int rightID = SkylineLayout[(int)(pos.Position.Y + 12), (int)(pos.Position.X + 28.5)]; int leftID = SkylineLayout[(int)(pos.Position.Y + 12), (int)(pos.Position.X + 26.5)]; // The following checks for the corner entities beside the ones above (forming a squre shape check) int bottomRID = SkylineLayout[(int)(pos.Position.Y + 11), (int)(pos.Position.X + 28.5)]; int bottomLID = SkylineLayout[(int)(pos.Position.Y + 11), (int)(pos.Position.X + 26.5)]; int topRID = SkylineLayout[(int)(pos.Position.Y + 13), (int)(pos.Position.X + 28.5)]; int topLID = SkylineLayout[(int)(pos.Position.Y + 13), (int)(pos.Position.X + 26.5)]; // The remaining checks the center entities on all four sides of the square checked above int outterBotID = SkylineLayout[(int)(pos.Position.Y + 10), (int)(pos.Position.X + 27.5)]; int outterTopID = SkylineLayout[(int)(pos.Position.Y + 14), (int)(pos.Position.X + 27.5)]; int outterRightID = SkylineLayout[(int)(pos.Position.Y + 12), (int)(pos.Position.X + 29.5)]; int outterLeftID = SkylineLayout[(int)(pos.Position.Y + 12), (int)(pos.Position.X + 25.5)]; /* x * x x x This is the shape that will get cut out of the terrain * x x x x x if the corrisponding location has an entity ID in the 2D array * x x x The Z axis is handled in the loops below and choosing which * x layer will be included or ignored based on the distance from the center entity. */ // This will be based to the collision system so all entities can be removed from furture checks List <string> names = new List <string>(); // Removes the center block (and each entity along the Z axis from it) for (int i = 0; i < 5; i++) { // Step1: check if the entity exists if (centerID != 0) { // Step2: remove that entity from the game scene entityManager.RemoveEntity(entityManager.FindEntity("Building" + (centerID + i))); // Step3: update list so system collision can be informed of the changes names.Add("Building" + (centerID + i)); } } // Step4: Set that location in the 2D array to 0 as this entity no longer exists SkylineLayout[(int)(pos.Position.Y + 12), (int)(pos.Position.X + 27.5)] = 0; // The above 4 steps are repeated for each part of the destruction pattern // The for loops just allow for the entities along the Z axis to be affect also for (int i = 0; i < 3; i++) { // Handles the bottom cubes from center if (bottomID != 0) { entityManager.RemoveEntity(entityManager.FindEntity("Building" + (bottomID + 2 + i))); names.Add("Building" + (bottomID + 2 + i)); SkylineLayout[(int)(pos.Position.Y + 11), (int)(pos.Position.X + 27.5)] = 0; if (bottomRID != 0 && i == 0) { entityManager.RemoveEntity(entityManager.FindEntity("Building" + (bottomRID + 4))); SkylineLayout[(int)(pos.Position.Y + 11), (int)(pos.Position.X + 28.5)] = 0; names.Add("Building" + (bottomRID + 4)); } if (bottomLID != 0 && i == 0) { entityManager.RemoveEntity(entityManager.FindEntity("Building" + (bottomLID + 4))); SkylineLayout[(int)(pos.Position.Y + 11), (int)(pos.Position.X + 26.5)] = 0; names.Add("Building" + (bottomLID + 4)); } if (outterBotID != 0 && i == 0) { entityManager.RemoveEntity(entityManager.FindEntity("Building" + (outterBotID + 4))); SkylineLayout[(int)(pos.Position.Y + 10), (int)(pos.Position.X + 27.5)] = 0; names.Add("Building" + (outterBotID + 4)); } } // Handles the top cubes from center if (topID != 0) { entityManager.RemoveEntity(entityManager.FindEntity("Building" + (topID + 2 + i))); SkylineLayout[(int)(pos.Position.Y + 13), (int)(pos.Position.X + 27.5)] = 0; names.Add("Building" + (topID + 2 + i)); if (topRID != 0 && i == 0) { entityManager.RemoveEntity(entityManager.FindEntity("Building" + (topRID + 4))); SkylineLayout[(int)(pos.Position.Y + 13), (int)(pos.Position.X + 28.5)] = 0; names.Add("Building" + (topRID + 4)); } if (topLID != 0 && i == 0) { entityManager.RemoveEntity(entityManager.FindEntity("Building" + (topLID + 4))); SkylineLayout[(int)(pos.Position.Y + 13), (int)(pos.Position.X + 26.5)] = 0; names.Add("Building" + (topLID + 4)); } if (outterTopID != 0 && i == 0) { entityManager.RemoveEntity(entityManager.FindEntity("Building" + (outterTopID + 4))); SkylineLayout[(int)(pos.Position.Y + 14), (int)(pos.Position.X + 27.5)] = 0; names.Add("Building" + (outterTopID + 4)); } } // Handles the right cubes from center if (rightID != 0) { entityManager.RemoveEntity(entityManager.FindEntity("Building" + (rightID + 2 + i))); SkylineLayout[(int)(pos.Position.Y + 12), (int)(pos.Position.X + 28.5)] = 0; names.Add("Building" + (rightID + 2 + i)); if (outterRightID != 0 && i == 0) { entityManager.RemoveEntity(entityManager.FindEntity("Building" + (outterRightID + 4))); SkylineLayout[(int)(pos.Position.Y + 12), (int)(pos.Position.X + 29.5)] = 0; names.Add("Building" + (outterRightID + 4)); } } // handles the left cubes from center if (leftID != 0) { entityManager.RemoveEntity(entityManager.FindEntity("Building" + (leftID + 2 + i))); SkylineLayout[(int)(pos.Position.Y + 12), (int)(pos.Position.X + 26.5)] = 0; names.Add("Building" + (leftID + 2 + i)); if (outterLeftID != 0 && i == 0) { entityManager.RemoveEntity(entityManager.FindEntity("Building" + (outterLeftID + 4))); SkylineLayout[(int)(pos.Position.Y + 12), (int)(pos.Position.X + 25.5)] = 0; names.Add("Building" + (outterLeftID + 4)); } } // Gain acccess to the collider system and update it with the list of entities that have been removed SystemColliderXY collider = (SystemColliderXY)systemManager.FindSystem("SystemColliderXY"); collider.RemoveDestructables(names.ToArray()); } }
/// <summary> /// Handles the projectile entity movement and collision triggers /// </summary> /// <param name="pCollide">The system collider being used</param> /// <param name="pTrajectory">Trajectory values calculated</param> private void HandleBananaMovement(ref SystemColliderXY pCollide, Vector2 pTrajectory) { // Used to time out banana if trajectory takes it out of camera view float MaxTravelTime = 6.0f; // Updates the bananas position with next increment of the trajectory calculation ComponentPosition pos = (ComponentPosition)entityManager.FindEntity("Banana").FindComponent(ComponentTypes.COMPONENT_POSITION); pos.Position = new Vector3(pTrajectory.X, pTrajectory.Y, pos.Position.Z); // Updates the collision system with new position for checks pCollide.UpdatePosition(pos.Position); // Used to determine whether collision happened bool hasCollided = false; // If collision system has found a trigger then take action if (pCollide.GetEntityCollisionTrigger() != null && pCollide.GetEntityCollisionTrigger() != "") { if (pCollide.GetEntityCollisionTrigger().Contains("Gorilla")) { SoundEffects[2].UpdateEmitterPosition(sceneManager.camera.Position); SoundEffects[2].PlayAudio(); EndRound(pCollide.GetEntityCollisionTrigger()); pCollide.ClearLastDestructable(); } else if (pCollide.GetEntityCollisionTrigger().Contains("Sun")) { ComponentTexture texture = (ComponentTexture)entityManager.FindEntity("SunFace").FindComponent(ComponentTypes.COMPONENT_TEXTURE); texture.Texture = ResourceManager.LoadTexture("Textures/sun_2.png"); hasHitSun = true; pCollide.ClearLastTrigger(); } else { SoundEffects[1].UpdateEmitterPosition(pos.Position); SoundEffects[1].VolumeOfAudio = 0.4f; SoundEffects[1].PlayAudio(); // Remove all building blocks around hit point DestroySkyline(pCollide.GetEntityCollisionTrigger()); // Clear collision system ready for next collision detection pCollide.ClearLastDestructable(); // Updates the collision system with new banana position pos.Position = new Vector3(0.0f, -50.0f, pos.Position.Z); pCollide.UpdatePosition(pos.Position); // Sets collision to true so game can progress to next player hasCollided = true; } } // If the banana has flown too long, fallen too low or has collided then progress to next player if (ProjectileTime >= MaxTravelTime || pTrajectory.Y < -5.0f || hasCollided) { // Used to determine which input is being entered (set to zero as current player is done) InputID = 0; // Readies time value for next trajectory ProjectileTime = 0.0f; // Switches which player is active if (isPlayer1) { isPlayer1 = false; } else { isPlayer1 = true; } } }
/// <summary> /// This method should be called on every game update, it checks if a banana is thrown and works outs its trajectory and handles its collision response /// </summary> /// <param name="dt">delta time from game update frame</param> private void Handle_BananaTrajectory(float dt) { // Checks if the player has entered both angle and power inputs before firing banana if (InputID >= 2) { // Trigger throwing sound effect (uses timer so will only trigger once per throw) if (ProjectileTime <= 0.0f) { SoundEffects[0].UpdateEmitterPosition(sceneManager.camera.Position); SoundEffects[0].VolumeOfAudio = 0.4f; SoundEffects[0].PlayAudio(); } // Gains access to the collision details SystemColliderXY collide = (SystemColliderXY)systemManager.FindSystem("SystemColliderXY"); // Collision action variables float angle, power; // Converts player input (string) to usable float values if (Angle == "") { angle = 0.0f; } else { angle = (float)((Math.PI / 180) * float.Parse(Angle)); } if (Power == "") { power = 0.0f; } else { power = float.Parse(Power) / 5.0f; } // Generic variables for both players inputs float playerX = 0.0f, playerY = 0.0f; // These values are used for when the banana spawns in so it doesnt trigger on the player immediatly if (isPlayer1) { playerX = G1X; playerY = G1Y + 1.5f; } else { playerX = G2X; playerY = G2Y + 1.5f; } // Based on which player is active the values will be edited accordingly if (isPlayer1) { if (WindSpeed < 0) { power -= power * WindSpeed; } else { power += power * (1.0f - WindSpeed); } } else { if (WindSpeed > 0) { power -= power * WindSpeed; } else { power += power * (1.0f - WindSpeed); } } // This is necassary for when the right player goes as the X values // needs to be inverted but you dont want to edit orignal timer float time = ProjectileTime; // Checks if its player 2 and inverts time if (!isPlayer1) { time *= -1; } // Banana Trajectory // X = current xPos, Y = current yPos, P = power, T = time of travel and G = gravity // x = X+P*COS(A)*T // y = Y+P*SIN(A)*T-G*T*T/2 float X = playerX + power * (float)Math.Cos(angle) * time; float Y = (playerY + 2.0f) + power * (float)Math.Sin(angle) * ProjectileTime - Gravity * ProjectileTime * (ProjectileTime / 2); // If time is 0 then this is the start of a turn so trigger should be cleared if (time == 0) { // This is required as the engine stores the last position of the banana // so when it moves up to above the player it causes a collision hit with // entities as it moves to its new psoition collide.UpdateLastPosition(new Vector3(playerX, playerY, -23.0f)); collide.ClearLastTrigger(); } // Increment the projectile time by time of this update pass (used for trajectory) ProjectileTime += dt; HandleBananaMovement(ref collide, new Vector2(X, Y)); } }