public override void Collect(RoomScene room, Character character, short gridX, short gridY) { byte subType = room.tilemap.GetMainSubType(gridX, gridY); byte border = subType == (byte)CoinsSubType.Coin ? (byte)10 : (byte)2; // Get the Direction of an Inner Boundary DirCardinal newDir = TileSolidImpact.RunOverlapTest(character, gridX * (byte)TilemapEnum.TileWidth + border, gridX * (byte)TilemapEnum.TileWidth + (byte)TilemapEnum.TileWidth - border, gridY * (byte)TilemapEnum.TileHeight + border, gridY * (byte)TilemapEnum.TileHeight + (byte)TilemapEnum.TileHeight - border); if (newDir == DirCardinal.None) { return; } // Collect Coins room.PlaySound(Systems.sounds.coin, 0.6f, gridX * (byte)TilemapEnum.TileWidth, gridY * (byte)TilemapEnum.TileHeight); if (subType == (byte)CoinsSubType.Coin) { Systems.handler.levelState.AddCoins(character, 1); } else if (subType == (byte)CoinsSubType.Gem) { Systems.handler.levelState.AddCoins(character, 10); } base.Collect(room, character, gridX, gridY); }
// An Inner Tile Impact checks for an additional, inner collision based on a designated rectangle. public static DirCardinal RunInnerImpact(GameObject actor, int x1, int x2, int y1, int y2) { // Check Overlap with Altered Border if (!CollideRect.IsTouchingRect(actor, x1, x2, y1, y2)) { return(DirCardinal.None); } DirCardinal newDir = CollideRect.GetDirectionOfCollision(actor, x1, x2, y1, y2); if (newDir == DirCardinal.Down) { actor.CollidePosDown(y1 - actor.bounds.Bottom); } else if (newDir == DirCardinal.Right) { actor.CollidePosRight(x1 - actor.bounds.Right); } else if (newDir == DirCardinal.Left) { actor.CollidePosLeft(x2 - actor.bounds.Left); } else if (newDir == DirCardinal.Up) { actor.CollidePosUp(y2 - actor.bounds.Top); } return(newDir); }
public virtual bool RunProjectileImpact(Projectile projectile) { // Some projectiles get destroyed on collision. if (projectile.CollisionType == ProjectileCollisionType.DestroyOnCollide) { projectile.Destroy(); return(true); } // Some projectiles bounce. if (projectile.CollisionType == ProjectileCollisionType.BounceOnFloor) { DirCardinal dir = CollideDetect.GetDirectionOfCollision(projectile, this); if (dir == DirCardinal.Down) { projectile.physics.AlignUp(this); projectile.BounceOnGround(); return(false); } projectile.Destroy(dir); return(true); } // Standard Collision return(false); }
public bool RunImpact(GameObject character, GameObject obj) { Character ch = (Character)character; // Specific Impact Types if (obj is Enemy) { return(((Enemy)obj).RunCharacterImpact(ch)); } if (obj is Item) { return(this.CharHitsItem(ch, (Item)obj)); } if (obj is Platform) { return(this.CharHitsPlatform(ch, (Platform)obj)); } if (obj is Projectile) { return(this.CharHitsProjectile(ch, (Projectile)obj)); } if (obj is Block) { return(this.CharHitsBlock(ch, (Block)obj)); } DirCardinal dir = CollideDetect.GetDirectionOfCollision(ch, obj); // Standard Collision return(Impact.StandardImpact(ch, obj, dir)); }
// One of these values gets set as 0, the other is set to -1 or 1 to represent the direction of movement. public void MoveSelector(sbyte slotX, sbyte slotY) { // Determine Sizes byte cols = (byte)Math.Ceiling((float)this.numOnPage / (float)this.PerRow); byte finalRow = (byte)(this.numOnPage - ((cols - 1) * this.PerRow)); sbyte toRow = (sbyte)(this.selectX + slotX); sbyte toCol = (sbyte)(this.selectY + slotY); // Moving Down if (slotY == 1) { // Leaves Paging Section if (toCol >= cols) { PagingExitRule exitRule = this.exits[DirCardinal.Down]; if (exitRule == PagingExitRule.Wrap) { this.selectY = 0; } else if (exitRule == PagingExitRule.NoWrap) /* No Change. Resists the Movement. */ } { else if (exitRule == PagingExitRule.LeaveArea) { this.exitDir = DirCardinal.Down; } }
// Check if an exact coordinate has a Blocking Square (Ground, BlockTile, HorizontalWall, etc.) public static bool IsBlockingCoord(TilemapLevel tilemap, int posX, int posY, DirCardinal dir) { short gridX = (short)(posX / (byte)TilemapEnum.TileWidth); short gridY = (short)(posY / (byte)TilemapEnum.TileHeight); return(CollideTile.IsBlockingSquare(tilemap, gridX, gridY, dir)); }
public static bool IsDirectionAllowed(byte objectId, DirCardinal dir) { // All Level Nodes can move in all directions. if (NodeData.IsObjectANode(objectId, false)) { return(true); } // Dots may or may not have direction allowance: if (NodeData.IsObjectADot(objectId)) { var dirsAllowed = NodeData.GetDotDirections(objectId); if (dir == DirCardinal.Up) { return(dirsAllowed.up); } if (dir == DirCardinal.Down) { return(dirsAllowed.down); } if (dir == DirCardinal.Left) { return(dirsAllowed.left); } if (dir == DirCardinal.Right) { return(dirsAllowed.right); } } return(false); }
public override bool RunImpact(RoomScene room, GameObject actor, short gridX, short gridY, DirCardinal dir) { // Get the Direction of an Inner Boundary DirCardinal newDir = TileSolidImpact.RunInnerImpact(actor, gridX * (byte)TilemapEnum.TileWidth, gridX * (byte)TilemapEnum.TileWidth + (byte)TilemapEnum.TileWidth, gridY * (byte)TilemapEnum.TileHeight, gridY * (byte)TilemapEnum.TileHeight + (byte)TilemapEnum.HalfHeight); if (newDir == DirCardinal.None) { return(false); } if (newDir == DirCardinal.Down) { // Get the SubType byte subType = room.tilemap.GetMainSubType(gridX, gridY); if (subType <= (byte)ConveyorSubType.Left) { actor.physics.SetExtraMovement(subType == (byte)ConveyorSubType.SlowLeft ? -2 : -4, 0); } else { actor.physics.SetExtraMovement(subType == (byte)ConveyorSubType.SlowRight ? 2 : 4, 0); } } if (actor is Character) { return(TileCharBasicImpact.RunWallImpact((Character)actor, dir)); } return(true); }
public bool EnemyHitsPlatform(Enemy enemy, Platform platform) { // If the enemy doesn't collide with tiles, they don't collide with platforms. if (enemy.CollideVal <= CollideEnum.NoTileCollide) { return(false); } DirCardinal dir = CollideDetect.GetDirectionOfCollision(enemy, platform); if (dir != DirCardinal.Down) { return(false); } // Enemy needs to track it's platform physics: enemy.physics.touch.TouchMover(platform); // Special Actor Collision for Platforms. // Only the Actor should run collision. Platform has no need to be touched, pushed, aligned, etc. // Additionally, it needs to skip the intend.Y test normally associated with CollideObjDown(platform). enemy.physics.touch.TouchDown(); enemy.physics.AlignUp(platform); enemy.physics.StopY(); return(true); }
public bool EnemyHitsBlock(Enemy enemy, Block block, DirCardinal dir) { // TODO: LOTS OF STUFF HERE. // TODO: CONVEYORS, WALL JUMPS, ETC return(Impact.StandardImpact(enemy, block, dir)); }
public override bool RunCharacterImpact(Character character) { DirCardinal dir = CollideDetect.GetDirectionOfCollision(character, this); if (dir == DirCardinal.Down && this.subType == (byte)GhostSubType.Hat) { ActionMap.Jump.StartAction(character, 2, 0, 4, true); } else { if (this.subType != (byte)GhostSubType.Hide) { if (this.subType == (byte)GhostSubType.Hat && this.posY - character.posY > 25) { return(false); } character.wounds.ReceiveWoundDamage(DamageStrength.Standard); } } if (this.subType == (byte)GhostSubType.Slimer) { return(Impact.StandardImpact(character, this, dir)); } return(false); }
public bool CharHitsPlatform(Character character, Platform platform) { DirCardinal dir = CollideDetect.GetDirectionOfCollision(character, platform); if (dir != DirCardinal.Down) { return(false); } // Character is "Dropping" through platforms: if (character.status.action is DropdownAction) { character.physics.touch.TouchMover(null); return(false); } // Activate the Platform platform.ActivatePlatform(); character.physics.touch.TouchMover(platform); // Assign the Character with the "OnMover" action, which will maintain their momentum after leaving the platform. ActionMap.OnMover.StartAction(character); // Special Character Collision for Platforms. // Only the Character should run collision. Platform has no need to be touched, pushed, aligned, etc. // Additionally, it needs to skip the intend.Y test normally associated with CollideObjDown(platform). character.physics.touch.TouchDown(); character.physics.AlignUp(platform); character.physics.StopY(); return(true); }
public override void Destroy(DirCardinal dir = DirCardinal.None, GameObject obj = null) { if (this.State == (byte)CommonState.Death) { return; } this.SetState((byte)CommonState.Death); this.physics.SetGravity(FInt.Create(0.7)); this.endFrame = Systems.timer.Frame + 12; Physics physics = this.physics; if (dir == DirCardinal.Right || dir == DirCardinal.Left) { physics.velocity.Y = physics.velocity.Y < 0 ? physics.velocity.Y * FInt.Create(0.25) : FInt.Create(-3); physics.velocity.X = dir == DirCardinal.Right ? FInt.Create(-1) : FInt.Create(1); } else if (dir == DirCardinal.Down || dir == DirCardinal.Up) { physics.velocity.X = physics.velocity.X * FInt.Create(0.25); physics.velocity.Y = dir == DirCardinal.Down ? FInt.Create(-4) : FInt.Create(1); } else { physics.velocity.X = FInt.Create(0); physics.velocity.Y = FInt.Create(-3); } this.room.PlaySound(Systems.sounds.shellThud, 0.4f, this.posX + 16, this.posY + 16); }
public override bool RunCharacterImpact(Character character) { DirCardinal dir = CollideDetect.GetDirectionOfCollision(character, this); if (dir == DirCardinal.Left) { TileCharBasicImpact.RunWallImpact(character, dir, DirCardinal.None); } else if (dir == DirCardinal.Right) { TileCharBasicImpact.RunWallImpact(character, dir, DirCardinal.None); } // Character is Beneath else if (dir == DirCardinal.Up) { if (this.physics.velocity.Y > 0) { character.wounds.ReceiveWoundDamage(DamageStrength.Standard); // Will kill if character is on ground. if (character.physics.touch.toBottom) { character.wounds.ReceiveWoundDamage(DamageStrength.InstantKill); return(true); } } TileCharBasicImpact.RunWallImpact(character, dir, DirCardinal.None); } return(Impact.StandardImpact(character, this, dir)); }
public void ResetCharacterStatus() { this.jumpsUsed = 0; this.nextSlide = 0; this.leaveWall = 0; this.grabDir = DirCardinal.None; }
// ActionMap.WallGrab.StartAction( character, dir ); public void StartAction(Character character, DirCardinal dir) { // If the Character is holding an item, there is no opportunity for wall jumping: if (character.heldItem.IsHeld) { return; } CharacterStatus status = character.status; // If the character is already grabbing the wall, end here. if (character.status.action is WallGrabAction) { return; } CharacterStats stats = character.stats; // If Able To Grab Walls if (stats.CanWallGrab) { this.EndLastActionIfActive(character); status.action = ActionMap.WallGrab; status.grabDir = dir; // Saves the direction of the grab for consistency in leap direction. // Update Shoes if (character.shoes is Shoes) { character.shoes.TouchWall(); } } // If character can Slide on Walls else if (stats.CanWallSlide) { status.grabDir = dir; // Saves the direction of the grab for consistency in leap direction. // Only begin sliding if you're moving downward: if (character.physics.velocity.Y > 0) { this.EndLastActionIfActive(character); status.action = ActionMap.WallGrab; } // If you're moving upward against the wall, you can still kick off using wall delay: else { status.leaveWall = Systems.timer.Frame + 7; } // Update Shoes if (character.shoes is Shoes) { character.shoes.TouchWall(); } } }
public override void Destroy(DirCardinal dir = DirCardinal.None, GameObject obj = null) { // Only destroy the projectile if it's not able to regenerate: if (this.regenEnergy == 0) { this.DestroyFinal(); return; } // Otherwise, deplete its energy. this.regenEnergy = 1; }
public void HorizontalCollide(GameObject obj, int bouncePosX, DirCardinal dir) { // Enemies die when from side. if (obj is EnemyLand) { if (this.physics.velocity.X != 0) { ((Enemy)obj).ReceiveWound(); } } }
public bool EnemyHitsEnemy(Enemy enemy, Enemy enemy2, DirCardinal dir) { if (enemy.CollideVal <= CollideEnum.NoTileCollide) { return(false); } if (enemy2.CollideVal <= CollideEnum.NoTileCollide) { return(false); } return(Impact.StandardImpact(enemy, enemy2, dir)); }
public void HorizontalCollide(GameObject obj, int bouncePosX, DirCardinal dir) { // Enemy Collision if (obj is EnemyLand) { if (this.physics.velocity.X != 0) { ((Enemy)obj).ReceiveWound(); } } // Character Collision else if (obj is Character) { Character character = (Character)obj; // If the Shell is moving toward the character: if (this.physics.velocity.X != 0) { // Damages the character, unlesss they're wearing the Bamboo Hat. if (!(character.hat is BambooHat)) { ((Character)obj).wounds.ReceiveWoundDamage(DamageStrength.Standard); this.BounceBack(bouncePosX); return; } } // Kick Shell character.heldItem.KickItem(this, dir == DirCardinal.Left ? DirCardinal.Right : DirCardinal.Left); return; } // Collides with another shell. else if (obj is Shell) { if (obj.physics.velocity.X == 0) { obj.Destroy(); } else { this.Destroy(); } } // Other objects. else { this.BounceBack(bouncePosX); } }
// A Facing Tile Impact only collides if the actor is colliding against the faced direction. public static bool RunImpact(GameObject actor, short gridX, short gridY, DirCardinal dir, DirCardinal facing) { if (dir == DirCardinal.None) { return(false); } // The Tile Faces Up. Collide if the Actor is moving is Down. if (facing == DirCardinal.Up) { if (dir == DirCardinal.Down) { actor.CollidePosDown(gridY * (byte)TilemapEnum.TileHeight - actor.bounds.Bottom); return(true); } } // The Tile Faces Down. Collide if the Actor is moving is Up. else if (facing == DirCardinal.Down) { if (dir == DirCardinal.Up) { actor.CollidePosUp(gridY * (byte)TilemapEnum.TileHeight + (byte)TilemapEnum.TileHeight - actor.bounds.Top); return(true); } } // The Tile Faces Left. Collide if the Actor is moving Right. else if (facing == DirCardinal.Left) { if (dir == DirCardinal.Right) { actor.CollidePosRight(gridX * (byte)TilemapEnum.TileWidth - actor.bounds.Right); return(true); } } // The Tile Faces Right. Collide if the Actor is moving is Left. else if (facing == DirCardinal.Right) { if (dir == DirCardinal.Left) { actor.CollidePosLeft(gridX * (byte)TilemapEnum.TileWidth + (byte)TilemapEnum.TileWidth - actor.bounds.Left); return(true); } } return(false); }
public bool CharHitsProjectile(Character character, Projectile projectile) { // Skip Character if they cast the projectile. if (projectile.ByCharacterId == character.id) { return(false); } DirCardinal dir = CollideDetect.GetDirectionOfCollision(character, projectile); // Set the projectile to bounce off of the screen: EndBounceParticle.SetParticle(character.room, Systems.mapper.atlas[(byte)AtlasGroup.Objects], projectile.SpriteName, new Vector2(projectile.posX, projectile.posY), Systems.timer.Frame + 40, 1, 0.5f, 0f); // Destroy the Projectile projectile.Destroy(); // If this projectile can be jumped on: if (projectile.SafelyJumpOnTop) { // Hit from above (projectile is below): if (dir == DirCardinal.Down) { //character.BounceUp(projectile.posX + projectile.bounds.MidX, 1, 0, 0); ActionMap.Jump.StartAction(character, 1, 0, 0, true, false); Systems.sounds.bulletJump.Play(); return(true); } // Hit from below (projectile is above): else if (dir == DirCardinal.Up && character.status.action is Action) { character.status.action.EndAction(character); } } // If wearing a hard hat, can ignore damage from above. if (dir == DirCardinal.Up) { if (character.hat is HardHat) { return(true); } } character.wounds.ReceiveWoundDamage(projectile.Damage); return(true); }
public bool CharHitsItem(Character character, Item item) { // Sport Ball if (item is SportBall) { return(((SportBall)item).RunCharacterImpact(character)); } // If this item is being held, skip. if (item.isHeld) { return(false); } // If the entity is intangible, don't collide with the Character. if (item.intangible > Systems.timer.Frame) { return(false); } DirCardinal dir = CollideDetect.GetDirectionOfCollision(character, item); // If item is hit from side: if (dir == DirCardinal.Left || dir == DirCardinal.Right) { // Check if Grabbing Item if (character.heldItem.WillPickupAttemptWork(item, dir)) { character.heldItem.PickUpItem(item); return(true); } } // If item is hit from above: else if (dir == DirCardinal.Up) { // Check if Grabbing Item if (character.heldItem.WillPickupAttemptWork(item, character.FaceRight ? DirCardinal.Right : DirCardinal.Left)) { character.heldItem.PickUpItem(item); return(true); } } // If we've made it this far, run standard collision with item: return(Impact.StandardImpact(character, item, dir)); }
public PagingSystem(byte numRows, byte numCols, short numItems) { this.exits = new Dictionary <DirCardinal, PagingExitRule>() { { DirCardinal.Left, PagingExitRule.Wrap }, { DirCardinal.Right, PagingExitRule.Wrap }, { DirCardinal.Up, PagingExitRule.Wrap }, { DirCardinal.Down, PagingExitRule.Wrap }, }; this.exitDir = DirCardinal.None; this.PerRow = numRows; this.PerPage = (byte)(numCols * numRows); this.NumberOfItems = numItems; this.ToPage(0); }
public virtual bool RunProjectileImpact(Projectile projectile) { // Can only be damaged if the projectile was cast by a Character. if (projectile.ByCharacterId == 0) { return(false); } // Special behavior for Magi-Balls. Projectiles faded out don't function. if (projectile is ProjectileMagi) { ProjectileMagi magi = (ProjectileMagi)projectile; if (!magi.CanDamage) { return(false); } } // Check if the enemy is resistant to the projectile. In most cases, destroy the projectile without harming the enemy. bool canResist = this.CanResistDamage(projectile.Damage); // If the projectile typicallly passes through walls, allow it to pass through indestructable enemies. if (canResist && projectile.CollisionType <= ProjectileCollisionType.IgnoreWallsDestroy) { return(false); } DirCardinal dir = CollideDetect.GetDirectionOfCollision(projectile, this); // Destroy the Projectile (unless it ignores walls) if (projectile.CollisionType != ProjectileCollisionType.IgnoreWallsSurvive || projectile is ProjectileMagi) { projectile.Destroy(dir); } // Wound the Enemy if (!canResist) { this.ReceiveWound(); } return(true); }
public bool EnemyHitsItem(Enemy enemy, Item item, DirCardinal dir) { if (item.isHeld) { return(false); } // Most Flight Enemies ignore item collisions. if (enemy is EnemyFlight) { if (!((EnemyFlight)enemy).shellCollision && item is Shell) { return(false); } } // If we've made it this far, run standard collision with item: return(Impact.StandardImpact(enemy, item, dir)); }
public static void DrawDirectionTiles(byte gridX, byte gridY, byte range = 6, bool up = false, bool left = false, bool right = false, bool down = false) { for (int y = gridY - range; y < gridY + range + 1; y++) { for (int x = gridX - range; x < gridX + range + 1; x++) { DirCardinal dir = NodeData.RelativeDirectionOfTiles((sbyte)(x - gridX), (sbyte)(y - gridY)); if ((dir == DirCardinal.Up && up) || (dir == DirCardinal.Down && down)) { Systems.spriteBatch.Draw(Systems.tex2dDarkRed, new Rectangle(x * (byte)WorldmapEnum.TileWidth - Systems.camera.posX, y * (byte)WorldmapEnum.TileHeight - Systems.camera.posY, (byte)WorldmapEnum.TileWidth, (byte)WorldmapEnum.TileHeight), Color.White * 0.35f); } else if ((dir == DirCardinal.Left && left) || (dir == DirCardinal.Right && right)) { Systems.spriteBatch.Draw(Systems.tex2dDarkGreen, new Rectangle(x * (byte)WorldmapEnum.TileWidth - Systems.camera.posX, y * (byte)WorldmapEnum.TileHeight - Systems.camera.posY, (byte)WorldmapEnum.TileWidth, (byte)WorldmapEnum.TileHeight), Color.White * 0.35f); } } } }
public void KickItem(Item item, DirCardinal dir) { item.intangible = Systems.timer.Frame + 5; // If the Shell is stationary, or character is hitting it from behind, or was wearing a Bamboo Hat. sbyte xStrength = 0; sbyte yStrength = 0; // Affect Kick by Input if (this.character.input.isDown(IKey.Down)) { xStrength = -2; } else if (this.character.input.isDown(IKey.Up)) { yStrength = 6; } // If facing the wrong way, reduce kick power: if (dir == DirCardinal.Left && this.character.FaceRight) { xStrength = -2; yStrength = 0; } if (dir == DirCardinal.Right && !this.character.FaceRight) { xStrength = -2; yStrength = 0; } item.physics.velocity.X = FInt.Create(dir == DirCardinal.Right ? item.KickStrength + xStrength : -(item.KickStrength + xStrength)); item.physics.velocity.Y = FInt.Create(-1.5 - yStrength); // Animate Shells if (item is Shell) { item.animate.SetAnimation(null, item.physics.velocity.X > 0 ? AnimCycleMap.Cycle4 : AnimCycleMap.Cycle4Reverse, 7, 1); } // Play Kick Sound this.character.room.PlaySound(Systems.sounds.shellBoop, 0.3f, this.character.posX + 16, this.character.posY + 16); this.ResetHeldItem(); }
public bool WillPickupAttemptWork(Item item, DirCardinal dirToward) { // Don't pick up an item if you're already carrying one. if (this.objHeld != null) { return(false); } // Make sure the action key is down: if (!this.character.input.isDown(IKey.XButton)) { return(false); } // Make sure you're facing the right direction (Shells don't apply to this rule). if (!(item is Shell)) { if (dirToward == DirCardinal.Left && this.character.FaceRight) { return(false); } if (dirToward == DirCardinal.Right && !this.character.FaceRight) { return(false); } } // Shells have special requirements for pickup: if (item is Shell) { // If the shell is moving quickly, it can't be picked up (unless you have the bamboo hat). if (Math.Abs(item.physics.velocity.X.RoundInt) > 4) { if (!(this.character.hat is BambooHat)) { return(false); } } } return(true); }
public override void Destroy(DirCardinal dir = DirCardinal.None, GameObject obj = null) { base.Destroy(); EndBounceParticle particle = EndBounceParticle.SetParticle(this.room, Systems.mapper.atlas[(byte)AtlasGroup.Objects], this.SpriteName, new Vector2(this.posX + this.bounds.Left - 2, this.posY + this.bounds.Top - 2), Systems.timer.Frame + 10, 3, 0.5f, 0.12f); if (dir == DirCardinal.Right || dir == DirCardinal.Left) { particle.vel.Y -= (float)CalcRandom.FloatBetween(0, 3); particle.vel.X = dir == DirCardinal.Right ? CalcRandom.FloatBetween(-3, 0) : CalcRandom.FloatBetween(0, 3); } else if (dir == DirCardinal.Down || dir == DirCardinal.Up) { particle.vel.Y = dir == DirCardinal.Down ? CalcRandom.FloatBetween(-4, -2) : CalcRandom.FloatBetween(-1, 1); particle.vel.X = (float)this.physics.velocity.X.ToDouble() * 0.35f + CalcRandom.FloatBetween(-1, 1); } this.room.PlaySound(Systems.sounds.shellThud, 0.4f, this.posX + 16, this.posY + 16); }