public override void act(Collider mover, bool shouting) { // if (the door is open) if (shouting && GameplayManager.Game.Keys.ContainsKey(GameState.GameFlag.REGISTRAR_DOOR_IS_OPEN) && GameplayManager.Game.Keys[GameState.GameFlag.REGISTRAR_DOOR_IS_OPEN]) { // Do nothing. Just let the user pass. } else if (GameplayManager.Game.Keys.ContainsKey(GameState.GameFlag.REGISTRAR_DOOR_IS_OPEN) && GameplayManager.Game.Keys[GameState.GameFlag.REGISTRAR_DOOR_IS_OPEN]) { GameplayManager.say(getDialogue(shouting)); } // else if (have the graduation form) else if (GameplayManager.Game.Keys.ContainsKey(GameState.GameFlag.PLAYER_ACCESSED_PUZZLE) && GameplayManager.Game.Keys[GameState.GameFlag.PLAYER_ACCESSED_PUZZLE]) { // Announce that the door has been opened. GameplayManager.say(getDialogue(shouting)); // Open the door. GameplayManager.Game.Keys[GameState.GameFlag.REGISTRAR_DOOR_IS_OPEN] = true; } // else else { // Announce that you can't do that, homeboy. GameplayManager.say(getDialogue(shouting)); // Send player back. if (shouting) { ((PlayerController)mover.m_owner).AnimationController.requestAnimation("left", AnimationController.AnimationCommand.Play); mover.handleMovement(new Vector2(-20, 0)); } } }
public Collider(ICollidable owner, Rectangle bounds, ColliderType type) { this.m_owner = owner; this.m_bounds = new DoubleRect(bounds.X, bounds.Y, bounds.Width, bounds.Height); this.m_bounds2 = new DoubleRect(bounds.X - 5, bounds.Y - 5, bounds.Width + 10, bounds.Height + 10); this.m_type = type; this.m_other = null; }
public override void handleImpact(Collider mover) { foreach (Character c in GameplayManager.Game.Characters) { if (c.ID == characterID) { c.act(mover, shouting); } } }
/// <summary> /// Scales back an attempted movement so that two colliders don't intersect. /// </summary> /// <param name="mover">Collider that is moving</param> /// <param name="other">Collider that the movement shouldn't be able to move into</param> /// <param name="deltaPosition">Amount that mover is trying to move</param> /// <returns>How much mover can move so as not to intersect other</returns> protected static Vector2 scaleBackVelocity(Collider mover, Collider other, Vector2 deltaPosition) { // whew! a lot work just to make it so that you can slide along objects when // using multiple directions const float EPS = 0.01f; DoubleRect dr2 = other.Bounds; double reducedX = deltaPosition.X; double reducedY = deltaPosition.Y; // Project x only movement and fix x velocity Vector2 temp = new Vector2(deltaPosition.X, 0); DoubleRect dr1 = mover.Bounds + temp; if (dr1.IntersectsWith(dr2)) if (deltaPosition.X > 0 && dr1.X + dr1.Width >= dr2.X) // moving right, rhs collision { double overlap = dr1.X + dr1.Width - dr2.X + EPS; reducedX = Math.Max(0.0f, deltaPosition.X - overlap); } else if (deltaPosition.X < 0 && dr1.X <= dr2.X + dr2.Width) // moving left, lhs collision { double overlap = (dr2.X + dr2.Width) - dr1.X + EPS; reducedX = Math.Min(0.0f, deltaPosition.X + overlap); } // Project y only movement and fix y velocity temp = new Vector2(0, deltaPosition.Y); dr1 = mover.Bounds + temp; if (dr1.IntersectsWith(dr2)) if (deltaPosition.Y > 0 && dr1.Y + dr1.Height >= dr2.Y) // moving down, bottom collision { double overlap = dr1.Y + dr1.Height - dr2.Y + EPS; reducedY = Math.Max(0.0f, deltaPosition.Y - overlap); } else if (deltaPosition.Y < 0 && dr1.Y <= dr2.Y + dr2.Height) // moving up, top collision { double overlap = (dr2.Y + dr2.Height) - dr1.Y + EPS; reducedY = Math.Min(0.0f, deltaPosition.Y + overlap); } // if neither X nor Y reduced, must be a corner collision // for now, we just won't allow this (if we allow, you can get stuck, but not bad) if (reducedX == deltaPosition.X && reducedY == deltaPosition.Y) { return Vector2.Zero; } return new Vector2((float)reducedX, (float)reducedY); }
private Color m_tint; // a tint to put on the decoration #endregion Fields #region Constructors /// <summary> /// Create a new decoration /// </summary> /// <param name="decorationSetTexture">Texture containing this decoration's graphic</param> /// <param name="indexNumber">An index into the texture, which finds this decoration's location in it</param> /// <param name="drawPos">Where in the area the decoration should be drawn</param> /// <param name="di">XML information about properties of the Decoration (load from Content)</param> /// <param name="tint">Color tint to apply to the graphic</param> public Decoration(GameTexture decorationSetTexture, int indexNumber, Vector2 drawPos, DecorationInfo di, Color tint) { this.m_texture = decorationSetTexture; this.m_drawIndex = indexNumber; this.m_drawPosition = drawPos; Rectangle bounds = new Rectangle( di.collision.X - di.graphic.X + (int)drawPos.X, di.collision.Y - di.graphic.Y + (int)drawPos.Y, di.collision.Width, di.collision.Height); this.m_collider = new Collider(this, bounds, ColliderType.Scenery, -1); // -1 is a flag for non-NPC colliders. this.m_tint = tint; }
public override void act(Collider mover, bool shouting) { setFlags(); if (!f_registrarDoorIsOpen && !f_deanFatigue) { GameplayManager.Game.Keys[GameState.GameFlag.DEAN_WAITING] = true; GameplayManager.Game.Keys[GameState.GameFlag.PLAYER_PARALYZED] = true; } else if (f_deanFatigue) { GameplayManager.Game.updateState(); } GameplayManager.say(getDialogue(shouting)); }
/// <summary> /// Determines how to handle various types of collisions. /// </summary> /// <param name="mover">Collider that is moving</param> /// <param name="other">Collider which was moved into</param> /// <param name="deltaPosition">Attempted movement by the mover</param> /// <param name="allowedMovement">Out param - amount of movement which is allowed</param> /// <returns>True if any movement is allowed, false otherwise</returns> public static bool handleMovement(Collider mover, Collider other, Vector2 deltaPosition, out Vector2 allowedMovement) { switch (mover.m_type) { case ColliderType.PC: return handlePCMovement(mover, other, deltaPosition, out allowedMovement); //break; //case ColliderType.NPC: // break; //case ColliderType.Effect: // break; //case ColliderType.Movable: // break; default: throw new Exception("Something's moving that shouldn't be"); } //return false; }
/// <summary> /// Moves a collider in the direction provided until it hits something /// </summary> /// <param name="mover">Collider which is moving</param> /// <param name="deltaPosition">Change in position the collider is trying to make</param> public void handleMovement(Collider mover, Vector2 deltaPosition) { double areaOfMovementX1 = Math.Min(mover.Bounds.X, mover.Bounds.X + deltaPosition.X); double areaOfMovementY1 = Math.Min(mover.Bounds.Y, mover.Bounds.Y + deltaPosition.Y); double areaOfMovementX2 = Math.Max(mover.Bounds.X + mover.Bounds.Width, mover.Bounds.X + mover.Bounds.Width + deltaPosition.X); double areaOfMovementY2 = Math.Max(mover.Bounds.Y + mover.Bounds.Height, mover.Bounds.Y + mover.Bounds.Height + deltaPosition.Y); DoubleRect areaOfMovement = new DoubleRect( areaOfMovementX1, areaOfMovementY1, areaOfMovementX2 - areaOfMovementX1, areaOfMovementY2 - areaOfMovementY1); //DoubleRect newbounds = mover.Bounds + deltaPosition; List<Collider> collisions = m_tree.Query(areaOfMovement); List<Collider>.Enumerator i = collisions.GetEnumerator(); Vector2 allowedMovement = deltaPosition; Vector2 temp; while (i.MoveNext()) { // we will usually collide with our old position - ignore that case if (i.Current != mover) { bool canMove = CollisionHandler.handleMovement(mover, i.Current, deltaPosition, out temp); if (!canMove) { return; // don't allow movement } if (allowedMovement.X > 0.0f) allowedMovement.X = Math.Min(allowedMovement.X, temp.X); else if (allowedMovement.X < 0.0f) allowedMovement.X = Math.Max(allowedMovement.X, temp.X); if (allowedMovement.Y > 0.0f) allowedMovement.Y = Math.Min(allowedMovement.Y, temp.Y); else if (allowedMovement.Y < 0.0f) allowedMovement.Y = Math.Max(allowedMovement.Y, temp.Y); } } mover.move(allowedMovement); }
/// <summary> /// Determines how to handle collisions involving the PC /// </summary> /// <returns>True if the PC can move, false otherwise</returns> protected static bool handlePCMovement(Collider mover, Collider other, Vector2 deltaPosition, out Vector2 allowedMovement) { switch (other.m_type) { case ColliderType.Scenery: allowedMovement = scaleBackVelocity(mover, other, deltaPosition); return true; case ColliderType.NPC: if (mover.m_type == ColliderType.PC) { mover.m_other = other; } allowedMovement = scaleBackVelocity(mover, other, deltaPosition); return true; case ColliderType.PC: if (mover.m_type == ColliderType.PC) { mover.m_other = other; } if (Quest.currentQuest == Quest.QUEST_TYPE.GET_COMPANION || GameplayManager.ActiveArea.GlobalLocation == Area.PARTY) { // if companion isn't in party, treat as NPC collider allowedMovement = scaleBackVelocity(mover, other, deltaPosition); } else { // allow movement through companion allowedMovement = deltaPosition; } return true; //case ColliderType.Effect: // break; //case ColliderType.Movable: // break; case ColliderType.Trigger: allowedMovement = deltaPosition; ((ITrigger)other.m_owner).handleImpact(mover); return true; default: allowedMovement = deltaPosition; return true; //throw new Exception("PC moved into something it shouldn't have"); } }
/// <summary> /// Determines how to handle collisions involving the PC /// </summary> /// <returns>True if the PC can move, false otherwise</returns> protected static bool handlePCMovement(Collider mover, Collider other, Vector2 deltaPosition, out Vector2 allowedMovement) { switch (other.m_type) { case ColliderType.Scenery: allowedMovement = scaleBackVelocity(mover, other, deltaPosition); return true; case ColliderType.NPC: allowedMovement = scaleBackVelocity(mover, other, deltaPosition); return true; //case ColliderType.Effect: // break; //case ColliderType.Movable: // break; case ColliderType.Trigger: allowedMovement = deltaPosition; ((ITrigger)other.m_owner).handleImpact(mover); return true; default: throw new Exception("PC moved into something it shouldn't have"); } }
public abstract void act(Collider mover, bool shouting);
public override void act(Collider mover, bool shouting) { setFlags(); if (watching) { if (example.Count > 0) { if (startPoint == null) { Behavior last = null; foreach (Behavior b in example) { if (last == null) { startPoint = b; } else { last.setNext(b); } last = b; } } else { List<LinkedList<Behavior>> paths = getAllPaths(startPoint); int[,] lcsGrid = getLCSGrid(example, paths[0]); int bestPath = 0; int[,] hold; for (int i = 1; i < paths.Count; i++) { hold = getLCSGrid(example, paths[i]); if (hold[hold.GetLength(0) - 1, hold.GetLength(1) - 1] > lcsGrid[lcsGrid.GetLength(0) - 1, lcsGrid.GetLength(1) - 1]) { lcsGrid = hold; bestPath = i; } } startPoint = null; LinkedList<Behavior> lcs = getLCS(lcsGrid, example, paths[bestPath], example.Count, paths[bestPath].Count); startPoint = mergePaths(example, paths[bestPath], lcs); paths.RemoveAt(bestPath); foreach (LinkedList<Behavior> llb in paths) { foldIn(llb, lcs); } } } GameplayManager.Game.Keys[GameState.GameFlag.SIMA_WATCHING] = false; } else if (openedPuzzle && !completedPuzzle) { example = new LinkedList<Behavior>(); GameplayManager.Game.Keys[GameState.GameFlag.SIMA_WAITING] = true; GameplayManager.Game.Keys[GameState.GameFlag.PLAYER_PARALYZED] = true; } GameplayManager.say(getDialogue(shouting)); //Thread t = new Thread(new ThreadStart(this.actHelper)); //t.Start(); //while (!t.IsAlive) ; }
/// <summary> /// Removes a particular collider from this CollisionDetector /// </summary> /// <param name="ci">Collider to remove</param> public void remove(Collider ci) { m_tree.Remove(ci); ci.forCollisionDetectorUseOnly(null); }
/// <summary> /// Adds a collider to the detector and marks that collider as being /// owned by this detector /// </summary> /// <param name="ci">Collider to register</param> public void register(Collider ci) { ci.forCollisionDetectorUseOnly(this); m_tree.Insert(ci); }
/// <summary> /// Code to actually transfer PC to a new Area when touched; called by collision handler /// </summary> /// <param name="other">Collider which has impacted the trigger</param> public override void handleImpact(Collider other) { if (other.m_owner == GameplayManager.Samus) { // TODO // remove this code once maps are pre-generated and area transition triggers already contain references // to their targets -- or, we might decide its just easier this way Point targetGlobalLocation; switch (m_side) { case AreaSideEnum.Top: targetGlobalLocation = new Point(this.m_owner.GlobalLocation.X, this.m_owner.GlobalLocation.Y - 1); break; case AreaSideEnum.Bottom: targetGlobalLocation = new Point(this.m_owner.GlobalLocation.X, this.m_owner.GlobalLocation.Y + 1); break; case AreaSideEnum.Left: targetGlobalLocation = new Point(this.m_owner.GlobalLocation.X - 1, this.m_owner.GlobalLocation.Y); break; case AreaSideEnum.Right: targetGlobalLocation = new Point(this.m_owner.GlobalLocation.X + 1, this.m_owner.GlobalLocation.Y); break; case AreaSideEnum.Other: throw new Exception("AreaTransitions on non-edges not fully impled"); break; default: throw new Exception("Unknown value for AreaSideEnum"); } if (m_target == null) { // check if it was created but we just don't have it this.m_target = WorldManager.GetArea(targetGlobalLocation); // still not created, so make it if (m_target == null) { m_target = Area.makeTestArea(targetGlobalLocation); } } // This code stays Point targetTile; // tile on other map on which player should arrive switch (m_side) { case AreaSideEnum.Top: targetTile = new Point(this.m_tilePos.X, Area.HEIGHT_IN_TILES - 1); break; case AreaSideEnum.Bottom: targetTile = new Point(this.m_tilePos.X, 0); break; case AreaSideEnum.Left: targetTile = new Point(Area.WIDTH_IN_TILES - 1, this.m_tilePos.Y); break; case AreaSideEnum.Right: targetTile = new Point(0, this.m_tilePos.Y); break; case AreaSideEnum.Other: throw new Exception("AreaTransitions on non-edges not fully impled"); default: throw new Exception("Unknown value for AreaSideEnum"); } GameplayManager.changeActiveArea(this.m_target, targetTile); } }
public override void act(Collider mover, bool shouting) { }
/// <summary> /// Certain tile #s in a TileSet may be marked as impassable. This function looks up those /// numbers and makes instances of those tiles in the Area impassable by registering the /// appropriate collision box. /// </summary> public void initializeTileColliders() { for (int i = 0; i < WIDTH_IN_TILES; ++i) { for (int j = 0; j < HEIGHT_IN_TILES; ++j) { if (!TileSet.tileInfos[Tiles[i, j]].passable) { Rectangle bounds = getTileRectangle(i, j); Collider ci = new Collider(null, bounds, ColliderType.Scenery); CollisionDetector.register(ci); } } } }
public ATrigger(Rectangle bounds) { m_collider = new Collider(this, bounds, ColliderType.Trigger); m_position = new Vector2(m_collider.Bounds.Center().X, m_collider.Bounds.Center().Y); }
public ATrigger(Rectangle bounds) { m_collider = new Collider(this, bounds, ColliderType.Trigger, -1); // -1 is a flag for non-NPC colliders. m_position = new Vector2(m_collider.Bounds.Center().X, m_collider.Bounds.Center().Y); }
public override void act(Collider mover, bool shouting) { setFlags(); if ((f_playerHasSignature && f_playerCompletedPuzzle) || (f_playerHasSignature && !f_playerAccessedPuzzle)) { GameplayManager.Game.Keys[GameState.GameFlag.PLAYER_WON] = true; } else if ((!f_explained) || (!f_registrarDoorIsOpen && f_explained && !f_riedlFatigue)) { GameplayManager.Game.Keys[GameState.GameFlag.RIEDL_HAS_EXPLAINED] = true; GameplayManager.Game.Keys[GameState.GameFlag.RIEDL_WAITING] = true; GameplayManager.Game.Keys[GameState.GameFlag.PLAYER_PARALYZED] = true; } else if (f_riedlFatigue) { GameplayManager.Game.updateState(); } GameplayManager.say(getDialogue(shouting)); }
public abstract void handleImpact(Collider mover);