public void DropItem() { if (this.objHeld == null) { return; } Item item = this.objHeld; item.intangible = Systems.timer.Frame + 7; // Check what Main Layer has present at the throw-release tile: TilemapLevel tilemap = this.character.room.tilemap; bool isBlocked = false; bool faceRight = this.character.FaceRight; isBlocked = CollideTile.IsBlockingSquare(tilemap, faceRight ? item.GridX2 : item.GridX, item.GridY, DirCardinal.Up); // If the drop tiles are blocked, see if we can drop it in the tile below. if (isBlocked) { int limitY = item.GridY * (byte)TilemapEnum.TileHeight + (byte)TilemapEnum.TileHeight; int dist = limitY - (item.posY + item.bounds.Top); // If we only have to drop it 24 pixels (or less), we can just lower the item slightly. if (dist < 24) { item.physics.MoveToPosY(limitY - item.bounds.Top); isBlocked = CollideTile.IsBlockingSquare(tilemap, faceRight ? item.GridX2 : item.GridX, item.GridY, DirCardinal.Up); } } // If the tile is still blocked, then a Y-reposition didn't work. We'll have to move it to character's tile. if (isBlocked) { int limitX; // NOTE: MUST have it like this. I don't understand the nuanced difference here, but it works. if (faceRight) { limitX = item.GridX2 * (byte)TilemapEnum.TileWidth; } else { limitX = item.GridX * (byte)TilemapEnum.TileWidth + (byte)TilemapEnum.TileWidth; } item.physics.MoveToPosX(limitX - (faceRight ? item.bounds.Right : item.bounds.Left)); } // Assign Minimal Drop Physics (to smooth natural look) item.physics.velocity.X = FInt.Create(this.character.physics.velocity.X.RoundInt / 3); item.physics.velocity.Y = FInt.Create(-1.5); // Play Drop Sound this.character.room.PlaySound(Systems.sounds.wooshSubtle, 0.5f, this.character.posX + 16, this.character.posY + 16); this.ResetHeldItem(); }
private void DetermineSlamDistance() { TilemapLevel tilemap = this.actor.room.tilemap; // We know the slammer's starting position. short gridX = this.actor.GridX; short gridY = this.actor.GridY; this.viewY = this.actor.posY + ((byte)TilemapEnum.TileHeight * 2); this.viewHeight = 0; // Scan for solid tiles beneath the slammer, up to 17 below (for a full screen) for (short testY = (short)(gridY + 2); testY < gridY + 19; testY++) { if (testY > tilemap.YCount + (byte)TilemapEnum.GapUp) { return; } // If there is a blocking tile at this height below the slammer, we can determine it's final Y-position after a slam: if (CollideTile.IsBlockingSquare(tilemap, gridX, testY, DirCardinal.Up) || CollideTile.IsBlockingSquare(tilemap, (short)(gridX + 1), testY, DirCardinal.Up)) { this.endY = testY * (byte)TilemapEnum.TileHeight; this.viewHeight = (short)(this.endY - this.viewY - 10); break; } } }
public TestTileCollisions() { this.levelScene = (LevelScene)Systems.scene; this.roomScene = (RoomScene)this.levelScene.rooms[0]; this.character = Systems.localServer.MyCharacter; this.tilemap = this.roomScene.tilemap; }
private void DoTeleport() { CharacterStatus status = this.character.status; // End the Teleport Action (to prevent re-teleportation) this.character.status.action.EndAction(this.character); // Get X, Y Coordinates from Distance and Radian float trueRotation = Radians.Normalize(status.actionFloat1); int xCoord = (int)Radians.GetXFromRotation(trueRotation, status.actionNum1) + character.posX + character.bounds.MidX; int yCoord = (int)Radians.GetYFromRotation(trueRotation, status.actionNum1) + character.posY + character.bounds.MidY; // Make sure teleportation is within world bounds. if (yCoord < (byte)TilemapEnum.GapUpPixel || yCoord > this.character.room.Height + (byte)TilemapEnum.GapUpPixel || xCoord < (byte)TilemapEnum.GapLeftPixel || xCoord > this.character.room.Width + (byte)TilemapEnum.GapRightPixel) { this.character.room.PlaySound(Systems.sounds.disableCollectable, 0.5f, this.character.posX + 16, this.character.posY + 16); return; } TilemapLevel tilemap = character.room.tilemap; // Make sure teleportation is to a valid open area. Blocking tiles will prevent teleportation. int xMid = xCoord - this.character.bounds.MidX; int yMid = yCoord - this.character.bounds.MidY; bool upLeft = CollideTile.IsBlockingCoord(tilemap, xMid + character.bounds.Left, yMid + character.bounds.Top - 1, DirCardinal.None); bool upRight = CollideTile.IsBlockingCoord(tilemap, xMid + character.bounds.Right, yMid + character.bounds.Bottom - 1, DirCardinal.None); bool downLeft = CollideTile.IsBlockingCoord(tilemap, xMid + character.bounds.Left, yMid + character.bounds.Top - 1, DirCardinal.None); bool downRight = CollideTile.IsBlockingCoord(tilemap, xMid + character.bounds.Right, yMid + character.bounds.Bottom - 1, DirCardinal.None); // If all positions are blocked, prevent teleport. if (upLeft && upRight && downLeft && downRight) { this.character.room.PlaySound(Systems.sounds.disableCollectable, 0.5f, this.character.posX + 16, this.character.posY + 16); return; } // If some positions are blocked, adjust position: if (upLeft && downLeft) { xMid += 12; } if (upRight && downRight) { xMid -= 12; } if (upLeft && upRight) { yMid += 12; } if (downLeft && downRight) { yMid -= 12; } this.character.room.PlaySound(Systems.sounds.pop, 1f, this.character.posX + 16, this.character.posY + 16); // Teleport Character this.character.physics.MoveToPos(xMid, yMid); }
protected override void Initialize() { // level = new TilemapLevel("./Maps/MagicLandCsv.json"); // level = new TilemapLevel("./Maps/test.json"); level = new TilemapLevel("./Maps/level.json"); base.Initialize(); }
public override bool Activate() { // Make sure the power can be activated if (!this.CanActivate()) { return(false); } // References Character character = this.character; // Determine Starting Position of Projectile relative to Character int posX = character.posX + character.bounds.MidX + (character.FaceRight ? 10 : -30); int posY = character.posY + character.bounds.Top + 5; // Play Sound character.room.PlaySound(this.sound, 1f, posX, posY); // Check if the tile placement is blocked: TilemapLevel tilemap = this.character.room.tilemap; bool isBlocked = CollideTile.IsBlockingCoord(tilemap, posX + 10 + (character.FaceRight ? 6 : -6), posY + 10, character.FaceRight ? DirCardinal.Right : DirCardinal.Left); // Prevent Throw if (isBlocked) { return(false); } // Prepare Velocity FInt velX = character.FaceRight ? this.xVel : this.xVel.Inverse; FInt velY = this.yVel; // Affect the Y-Velocity of the projectile if holding UP or DOWN this.AffectByInput(ref velX, ref velY); // Apply Character's Momentum (if applicable) if (this.multMomentum > 0) { velX += character.physics.velocity.X * this.multMomentum; velY += character.physics.velocity.Y * this.multMomentum * FInt.Create(0.5); } // Launch Projectile this.Launch(posX, posY, velX, velY); return(true); }
// Returns TRUE if the character can phase to the horizontal location. public bool TestPhasingHorizontal(Character character, TilemapLevel tilemap, short toX, DirCardinal dir) { bool blocking = CollideTile.IsBlockingSquare(tilemap, toX, character.GridY, dir); if (blocking) { return(false); } if (character.GridY != character.GridY2) { blocking = CollideTile.IsBlockingSquare(tilemap, toX, character.GridY2, dir); } return(!blocking); }
// Returns TRUE if the character can phase to the vertical location. public bool TestPhasingVertical(Character character, TilemapLevel tilemap, short toY, DirCardinal dir) { bool blocking = CollideTile.IsBlockingSquare(tilemap, character.GridX, toY, dir); if (blocking) { return(false); } if (character.GridX != character.GridX2) { blocking = CollideTile.IsBlockingSquare(tilemap, character.GridX2, toY, dir); } return(!blocking); }
public override bool Activate() { // Make sure the power can be activated if (!this.CanActivate()) { return(false); } // References Character character = this.character; // Determine Starting Position of Projectile relative to Character int posX = character.posX + character.bounds.MidX + (character.FaceRight ? 6 : -30); int posY = character.posY + character.bounds.Top + 5; // Play Sound character.room.PlaySound(this.sound, 1f, posX, posY); // Check if the tile placement is blocked (only applies to bolts that collide with tiles). if (this is BoltBlue) { TilemapLevel tilemap = this.character.room.tilemap; bool isBlocked = CollideTile.IsBlockingCoord(tilemap, posX + (character.FaceRight ? 10 : 4), posY, character.FaceRight ? DirCardinal.Right : DirCardinal.Left); // Prevent Throw if (isBlocked) { return(false); } } // Prepare Velocity FInt velX = character.FaceRight ? FInt.Create(this.xVel) : FInt.Create(-this.xVel); FInt velY = FInt.Create(this.yVel); // Affect the Y-Velocity of the projectile if holding UP or DOWN this.AffectByInput(ref velX, ref velY); // Launch Projectile this.Launch(character, posX, posY, velX, velY); return(true); }
public static void DetonateTNT(RoomScene room, int posX, int posY, short width, short height) { Systems.camera.BeginCameraShake(13, 7); room.PlaySound(Systems.sounds.explosion, 1f, posX + (int)Math.Round(width * 0.5), posY + (int)Math.Round(height * 0.5)); List <GameObject> objects = CollideRect.FindAllObjectsTouchingArea( room.objects[(byte)LoadOrder.Enemy], posX, posY, width, height ); // Loop through Enemies and destroy any that can be destroyed by TNT. foreach (GameObject obj in objects) { Enemy enemy = (Enemy)obj; enemy.DamageByTNT(); } ; TilemapLevel tilemap = room.tilemap; // Destroy Chompers Within Area of Effect short startX = Math.Max((short)0, (short)Math.Floor((double)(posX / (byte)TilemapEnum.TileWidth))); short startY = Math.Max((short)0, (short)Math.Floor((double)(posY / (byte)TilemapEnum.TileHeight))); short endX = Math.Min(tilemap.XCount, (short)Math.Floor((double)((posX + width) / (byte)TilemapEnum.TileWidth))); short endY = Math.Min((short)(tilemap.YCount + TilemapEnum.GapUp), (short)Math.Floor((double)((posY + height) / (byte)TilemapEnum.TileHeight))); // Locate Chompers var tilesFound = tilemap.GetTilesByMainIDsWithinArea(new byte[7] { (byte)TileEnum.ChomperFire, (byte)TileEnum.ChomperGrass, (byte)TileEnum.ChomperMetal, (byte)TileEnum.Plant, (byte)TileEnum.Box, (byte)TileEnum.Brick, (byte)TileEnum.Leaf }, startX, startY, endX, endY); var TileDict = Systems.mapper.TileDict; foreach (var tileInfo in tilesFound) { TileObject tile = TileDict[tileInfo.tileId]; if (tile is Chomper) { ((Chomper)tile).DestroyChomper(room, tileInfo.gridX, tileInfo.gridY); } } }
public void ThrowItem(bool useXMomentum = false) { if (this.objHeld == null) { return; } Item item = this.objHeld; // Item will release in the direction the character does. item.SetDirection(this.character.FaceRight); // Check what Main Layer has present at the throw-release tile: TilemapLevel tilemap = this.character.room.tilemap; bool isBlocked = CollideTile.IsBlockingSquare(tilemap, item.GridX, item.GridY, DirCardinal.Up); if (!isBlocked && item.GridX != item.GridX2) { isBlocked = CollideTile.IsBlockingSquare(tilemap, item.GridX2, item.GridY, DirCardinal.Up); } // Prevent Throw if (isBlocked) { this.DropItem(); return; } // Assign Item Physics + Thrown Properties item.intangible = Systems.timer.Frame + 5; item.releasedMomentum = useXMomentum ? (sbyte)Math.Round(this.character.physics.velocity.X.RoundInt / 2.5) : (sbyte)0; item.physics.velocity.X = FInt.Create(item.releasedMomentum); item.physics.velocity.Y = FInt.Create(-item.ThrowStrength); // Play Throw Sound this.character.room.PlaySound(Systems.sounds.wooshSubtle, 1f, this.character.posX + 16, this.character.posY + 16); // No longer holding object: this.ResetHeldItem(); }
private void PlaceDetectorsAbove(RoomScene room, short gridX, short gridY) { TilemapLevel tilemap = room.tilemap; // Scan for solid tiles above the flag, up to 18 above (for a full screen) for (short testY = (short)(gridY - 1); testY > gridY - 18; testY--) { if (testY < (byte)TilemapEnum.GapUp) { return; } // If there is a blocking tile at this grid sqare, stop placements. if (CollideTile.IsBlockingSquare(tilemap, gridX, testY, DirCardinal.Down)) { return; } // Otherwise, add a Detector. room.tilemap.SetMainTile(gridX, testY, (byte)TileEnum.DetectCheckpointPass, 0); } }
private PhaseSuccess PerformBlink() { Character character = this.character; RoomScene room = character.room; TilemapLevel tilemap = room.tilemap; // Vertical Phasing if (character.input.isDown(IKey.Down) || character.input.isDown(IKey.Up)) { DirCardinal dir = character.input.isDown(IKey.Down) ? DirCardinal.Down : DirCardinal.Up; short toY; if (dir == DirCardinal.Down) { toY = (short)(character.GridY2 + 2); if (toY >= (short)(tilemap.YCount + (byte)TilemapEnum.GapUp - 1)) { return(PhaseSuccess.Success); } } else { toY = (short)(character.GridY - 2); if (toY <= (short)TilemapEnum.GapUp + 1) { return(PhaseSuccess.Success); } } // Phase to the given location if it's open: if (this.TestPhasingVertical(character, tilemap, toY, dir)) { character.physics.MoveToPosY(toY * (byte)TilemapEnum.TileHeight); return(PhaseSuccess.Success); } // If the last location is blocked, try the next: toY = (short)(toY + (dir == DirCardinal.Down ? 1 : -1)); if (this.TestPhasingVertical(character, tilemap, toY, dir)) { character.physics.MoveToPosY(toY * (byte)TilemapEnum.TileHeight); return(PhaseSuccess.Success); } } // Horizontal Phasing else if (character.input.isDown(IKey.Left) || character.input.isDown(IKey.Right)) { DirCardinal dir = character.input.isDown(IKey.Left) ? DirCardinal.Left : DirCardinal.Right; short toX; if (dir == DirCardinal.Right) { toX = (short)(character.GridX2 + 2); if (toX >= (short)(tilemap.XCount + (byte)TilemapEnum.GapLeft - 1)) { return(PhaseSuccess.Success); } } else { toX = (short)(character.GridX - 2); if (toX <= (short)TilemapEnum.GapLeft + 1) { return(PhaseSuccess.Success); } } // Phase to the given location if it's open: if (this.TestPhasingHorizontal(character, tilemap, toX, dir)) { character.physics.MoveToPosX(toX * (byte)TilemapEnum.TileWidth); return(PhaseSuccess.Success); } // If the last location is blocked, try the next: toX = (short)(toX + (dir == DirCardinal.Right ? 1 : -1)); if (this.TestPhasingHorizontal(character, tilemap, toX, dir)) { character.physics.MoveToPosX(toX * (byte)TilemapEnum.TileWidth); return(PhaseSuccess.Success); } } // No inputs were provided. else { return(PhaseSuccess.NoAction); } return(PhaseSuccess.Fail); }
public static void Detonate(RoomScene room, int midX, int midY) { TilemapLevel tilemap = room.tilemap; int gridX = (int)Math.Floor((double)(midX / (byte)TilemapEnum.TileWidth)); int gridY = (int)Math.Floor((double)(midY / (byte)TilemapEnum.TileHeight)); // Destroy Enemies Within Area of Effect List <GameObject> enemiesFound = CollideRect.FindAllObjectsTouchingArea(room.objects[(byte)LoadOrder.Enemy], midX - 144, midY - 96, 288, 192); foreach (GameObject enemy in enemiesFound) { ((Enemy)enemy).Die(DeathResult.Knockout); } // Heavily Damage Characters Within Area of Effect List <GameObject> charsFound = CollideRect.FindAllObjectsTouchingArea(room.objects[(byte)LoadOrder.Character], midX - 144, midY - 96, 288, 192); foreach (GameObject character in charsFound) { ((Character)character).wounds.ReceiveWoundDamage(DamageStrength.Major, true); ((Character)character).wounds.ReceiveWoundDamage(DamageStrength.Major, true); ((Character)character).wounds.ReceiveWoundDamage(DamageStrength.Major, true); } // Destroy Certain Tiles Within Area of Effect short startX = (short)Math.Max(0, gridX - 3); short startY = (short)Math.Max(0, gridY - 2); short endX = (short)Math.Min(tilemap.XCount + (byte)TilemapEnum.GapLeft - 1, gridX + 3); short endY = (short)Math.Min(tilemap.YCount + (byte)TilemapEnum.GapUp - 1, gridY + 2); // Locate Tiles: Chompers, Boxes, Bricks, Leafs, etc. var tilesFound = tilemap.GetTilesByMainIDsWithinArea(new byte[7] { (byte)TileEnum.ChomperFire, (byte)TileEnum.ChomperGrass, (byte)TileEnum.ChomperMetal, (byte)TileEnum.Plant, (byte)TileEnum.Box, (byte)TileEnum.Brick, (byte)TileEnum.Leaf }, startX, startY, endX, endY); var TileDict = Systems.mapper.TileDict; foreach (var tileInfo in tilesFound) { TileObject tile = TileDict[tileInfo.tileId]; if (tile is Chomper) { ((Chomper)tile).DestroyChomper(room, tileInfo.gridX, tileInfo.gridY); } else if (tile is Brick) { ((Brick)tile).DestroyBrick(room, tileInfo.gridX, tileInfo.gridY); } else if (tile is Box) { ((Box)tile).DestroyBox(room, tileInfo.gridX, tileInfo.gridY); } else if (tile is Leaf) { ((Leaf)tile).TriggerEvent(room, tileInfo.gridX, tileInfo.gridY, 0); } } // Display Particle Effect ExplodeEmitter.BoxExplosion(room, "Particles/GrenadeFrag", midX, midY, 20, 15); ExplodeEmitter.BoxExplosion(room, "Particles/GrenadeFrag", midX, midY, 70, 50); room.PlaySound(Systems.sounds.explosion, 0.4f, midX, midY); // Camera Shake Systems.camera.BeginCameraShake(35, 6); }