//---------------------------------------------------------------- //determines the action to be preformed for special cases...that is objects or screen models that private void DetermineAction() { //this if determines if the object in front of the users is a special case (a subclass of the ScreenModel Class) ScreenModel SpecialObject = ObjectIsInfront(); if (SpecialObject != null) { if (SpecialObject.GetType() != typeof(ScreenModel)) { //gets the action key from the user if (((LastMouseState.LeftButton != Mouse.GetState().LeftButton) && (Mouse.GetState().LeftButton == ButtonState.Pressed)) || ((GamePad.GetState(PlayerIndexValue).IsConnected) && (((GamePad.GetState(PlayerIndexValue).IsButtonDown(Buttons.Y)) && (!GamePadLastState.IsButtonDown(Buttons.Y)))))) { //switch back reticle, unless dictated by this special method this.ReticleToDraw = SpecialObject.SpecialReticle(); //special case of a wall; you can change the wall in forge but not in regular mode if (SpecialObject.GetType() == typeof(Wall)) this.ReticleToDraw = ((Wall)SpecialObject).SpecialReticle(IsForgeModeRunning); //not sure why nick did this...but w/e...maybe he just doesn't get polymorphism yet else if (SpecialObject.GetType() == typeof(Door)) ((Door)SpecialObject).Action(Content, VisibleObjects, graphics,this); else SpecialObject.Action(this.CurrentRoom, Content, models, graphics); } } } }
//-------------------------------------------------------------------------------------------------------------- //---------------------------------------------------------------------- //method that checks if the object is visibly in front of the user //when the bool argument is true, it will return values/change the reticle based on an object that has a special action, //not whether or not it should be picked up public ScreenModel ObjectIsInfront() { //******CONCEPT: ********* //1) "Highlights" a single possible object that can be picked up //this should be the object that best lines up with the center of the reticle ScreenModel TestModel = null; //Takes the list of a few objects within the threshold and finds the one that is the shortest distance away float? ClosestDist = float.MaxValue; //list of screen models that ScreenModel TestModelClosest = null; //distance between objects, if found float? Distance = 0f; Ray TestRay = new Ray(CameraPosition, CameraAngle3); //Console.WriteLine(TestRay.ToString()); for (int cntr = 0; cntr < this.NearObjects.Count; cntr++) { if (((NearObjects[cntr].PickUpable) || (NearObjects[cntr].GetType() == typeof(Door)) || (NearObjects[cntr].GetType() == typeof(ComputerConsole))) || IsForgeModeRunning) if (this.NearObjects[cntr].CollisionType == ObjectTypes.Box) { //checks bounding boxes, if applicable if (this.NearObjects[cntr].GetType() == typeof(Wall)) { foreach (OrientedBoundingBox Box in NearObjects[cntr].MovingBoxes) if ((Distance = Box.Intersects(TestRay)) != null) { TestModel = this.NearObjects[cntr]; //3) Checks to see if the object is within a specified distance away using a ray //Uses the position of the model and a direction vector (in front of the camera) to find distance away if ((TestModelClosest != null) && (TestModelClosest.GetType() == typeof(Wall)) && (DataValues.VectorDistance(TestModelClosest.MovingBoxes[0].HalfExtent) > DataValues.VectorDistance(Box.HalfExtent))) { //stores the closest of the models at the same time as finding models that //are within the threshold; more effecient than going through yet another list TestModelClosest = TestModel; ClosestDist = Distance - DataValues.VectorDistance(Box.HalfExtent); break; } if ((Distance - DataValues.VectorDistance(Box.HalfExtent) <= DataValues.MaxObjectDistance) && (Distance - DataValues.VectorDistance(Box.HalfExtent) < ClosestDist)) { //stores the closest of the models at the same time as finding models that //are within the threshold; more effecient than going through yet another list TestModelClosest = TestModel; ClosestDist = Distance - DataValues.VectorDistance(Box.HalfExtent); break; } } } else if (((Distance = this.NearObjects[cntr].GetBoundingBoxes().Intersects(TestRay)) != null)) { TestModel = this.NearObjects[cntr]; //3) Checks to see if the object is within a specified distance away using a ray //Uses the position of the model and a direction vector (in front of the camera) to find distance away if((TestModelClosest!=null)&&(TestModelClosest.GetType()==typeof(Wall))&&(DataValues.VectorDistance(TestModelClosest.MovingBoxes[0].HalfExtent)>Distance)) { TestModelClosest = TestModel; ClosestDist = Distance; break; } if ((Distance <= DataValues.MaxObjectDistance) && (Distance < ClosestDist)) { //stores the closest of the models at the same time as finding models that //are within the threshold; more effecient than going through yet another list TestModelClosest = TestModel; ClosestDist = Distance; break; } } } //idk if we still use this but let's just leave it in case... else { if (TestRay.Intersects(this.NearObjects[cntr].GetBoundingSpheres()) != null) { TestModel = this.NearObjects[cntr]; Distance = TestRay.Intersects(TestModel.GetBoundingSpheres()); if ((Distance <= DataValues.MaxObjectDistance) && (Distance < ClosestDist)) { //stores the closest of the models at the same time as finding models that //are within the threshold; more effecient than going through yet another list TestModelClosest = TestModel; ClosestDist = Distance; } } } } //after one has found the closest, re-assing test model TestModel = TestModelClosest; //2) Checks object to see if it is of pickupable type //or if it's a special object with an action if (TestModel == null) { //object cannot be picked up this.ReticleToDraw = DataValues.ReticleType.Normal; return (null); } //Console.WriteLine(TestModel.GetType().ToString()); //checks if it is in that distance...and is a regular screem model object if ((ClosestDist <= DataValues.MaxObjectDistance) && ((TestModel.GetType() == typeof(ScreenModel)) || (TestModel.GetType() == typeof(Wall))) && (TestModel.PickUpable == true)) { //object can be picked up, change the reticle this.ReticleToDraw = DataValues.ReticleType.ObjectPickup; //return the model return (TestModel); } //checks if it is in that distance if it's a special screen model object if ((ClosestDist <= DataValues.MaxObjectDistance) && ((TestModel.GetType() != typeof(ScreenModel)) || (TestModel.GetType() != typeof(Wall)))) { //changes color while holding the object this.ReticleToDraw = DataValues.ReticleType.ActionBtn; //you can only edit walls in forge world...this hides the reticle when the user is not in forge world if (TestModel.GetType() == typeof(Wall)) this.ReticleToDraw = ((Wall)TestModel).SpecialReticle(IsForgeModeRunning); //return the model return (TestModel); } //or return nothing, our friend null, which will cause an exception to be caught, acting as a general check //object cannot be picked up if (!this.HoldingObjectTrue) this.ReticleToDraw = DataValues.ReticleType.Normal; return (null); }
//---------------------------------------------------------------- //method that allows the user to pick up objects public void PickUpObject() { HoldingObject.Velocity = Vector3.Zero; //tells the object that it is being held HoldingObject.IsBeingHeld = true; HoldingObjectTrue = true; float Distance=4f; if (this.HoldingObjectDistanceSet) if (HoldingObject.CollisionType == ObjectTypes.Box) { if (DataValues.VectorDistance(HoldingObject.GetBoundingBoxes().Max - HoldingObject.Position) + 4 > Distance) Distance = 4f + DataValues.VectorDistance(HoldingObject.GetBoundingBoxes().Max - HoldingObject.Position); } else { foreach (ModelMesh Mesh in HoldingObject.MyModel.Meshes) if (Mesh.BoundingSphere.Radius + 4 > Distance) Distance = 4f + Mesh.BoundingSphere.Radius; } else Distance = DataValues.VectorDistance(CameraPosition - HoldingObject.Position - Velocity); //Ray TestRay = new Ray(CameraPosition, CameraAngle3); HoldingObject.Position = CameraPosition + (Distance * CameraAngle3); //HoldingObject.MoveModelBox(Position-HoldingObject.Position); //moves model box if this is a box colliding type if (HoldingObject.CollisionType == ObjectTypes.Box) { //first time the last position has to be tracked HoldingObjectLastPos = HoldingObject.Position; } //changes color while holding the object this.ReticleToDraw = DataValues.ReticleType.HoldingObj; }
//method that allows the user to drop objects public void DropObject() { //tells the object that it is not being held HoldingObject.IsBeingHeld = false; //the object is no longer being held HoldingObjectTrue = false; //set the object to fall; this will be picked up in the update method for this object and thus independent from the user's control HoldingObject.IsCurrentlyFalling = true; //recreates a bounding box if needed (but bounding sphere always works) if (HoldingObject.CollisionType == ObjectTypes.Box) { //anthony's much easier version HoldingObject.BoundingSetup(); //correction for position //--------------------------------------------- //methods that handle rotation of the bounding box //HoldingObject.ConverToOBB(); //HoldingObject.ConverToABB(); /* //takes the initial position of the bounding box (when loaded) Vector3 ChangeVect = HoldingObject.Position - HoldingObject.LocalPos; //translates the change for the bounding box HoldingObject.MovingBox.Min += ChangeVect; HoldingObject.MovingBox.Max += ChangeVect; */ //restores that initial box (current position) //HoldingObject.LocalPos = HoldingObject.Position; //HoldingObject.LocalBox = HoldingObject.MovingBox; //--------------------------------------------- } //changes color back to white...which will get changed next loop cycle anyway.... this.ReticleToDraw = DataValues.ReticleType.Normal; }