Files
tbd-station-14/Content.Server/Arcade/BlockGame/BlockGame.Pieces.cs
2023-06-15 21:25:25 +10:00

239 lines
8.8 KiB
C#

using Content.Shared.Arcade;
using System.Linq;
namespace Content.Server.Arcade.BlockGame;
public sealed partial class BlockGame
{
/// <summary>
/// The set of types of game pieces that exist.
/// Used as templates when creating pieces for the game.
/// </summary>
private readonly BlockGamePieceType[] _allBlockGamePieces;
/// <summary>
/// The set of types of game pieces that exist.
/// Used to generate the templates used when creating pieces for the game.
/// </summary>
private enum BlockGamePieceType
{
I,
L,
LInverted,
S,
SInverted,
T,
O
}
/// <summary>
/// The set of possible rotations for the game pieces.
/// </summary>
private enum BlockGamePieceRotation
{
North,
East,
South,
West
}
/// <summary>
/// A static extension for the rotations that allows rotating through the possible rotations.
/// </summary>
private static BlockGamePieceRotation Next(BlockGamePieceRotation rotation, bool inverted)
{
return rotation switch
{
BlockGamePieceRotation.North => inverted ? BlockGamePieceRotation.West : BlockGamePieceRotation.East,
BlockGamePieceRotation.East => inverted ? BlockGamePieceRotation.North : BlockGamePieceRotation.South,
BlockGamePieceRotation.South => inverted ? BlockGamePieceRotation.East : BlockGamePieceRotation.West,
BlockGamePieceRotation.West => inverted ? BlockGamePieceRotation.South : BlockGamePieceRotation.North,
_ => throw new ArgumentOutOfRangeException(nameof(rotation), rotation, null)
};
}
/// <summary>
/// A static extension for the rotations that allows rotating through the possible rotations.
/// </summary>
private struct BlockGamePiece
{
/// <summary>
/// Where all of the blocks that make up this piece are located relative to the origin of the piece.
/// </summary>
public Vector2i[] Offsets;
/// <summary>
/// The color of all of the blocks that make up this piece.
/// </summary>
private BlockGameBlock.BlockGameBlockColor _gameBlockColor;
/// <summary>
/// Whether or not the block should be able to rotate about its origin.
/// </summary>
public bool CanSpin;
/// <summary>
/// Generates a list of the positions of each block comprising this game piece in worldspace.
/// </summary>
/// <param name="center">The position of the game piece in worldspace.</param>
/// <param name="rotation">The rotation of the game piece in worldspace.</param>
public readonly Vector2i[] Positions(Vector2i center, BlockGamePieceRotation rotation)
{
return RotatedOffsets(rotation).Select(v => center + v).ToArray();
}
/// <summary>
/// Gets the relative position of each block comprising this piece given a rotation.
/// </summary>
/// <param name="rotation">The rotation to be applied to the local position of the blocks in this piece.</param>
private readonly Vector2i[] RotatedOffsets(BlockGamePieceRotation rotation)
{
var rotatedOffsets = (Vector2i[]) Offsets.Clone();
//until i find a better algo
var amount = rotation switch
{
BlockGamePieceRotation.North => 0,
BlockGamePieceRotation.East => 1,
BlockGamePieceRotation.South => 2,
BlockGamePieceRotation.West => 3,
_ => 0
};
for (var i = 0; i < amount; i++)
{
for (var j = 0; j < rotatedOffsets.Length; j++)
{
rotatedOffsets[j] = rotatedOffsets[j].Rotate90DegreesAsOffset();
}
}
return rotatedOffsets;
}
/// <summary>
/// Gets a list of all of the blocks comprising this piece in worldspace.
/// </summary>
/// <param name="center">The position of the game piece in worldspace.</param>
/// <param name="rotation">The rotation of the game piece in worldspace.</param>
public readonly BlockGameBlock[] Blocks(Vector2i center, BlockGamePieceRotation rotation)
{
var positions = Positions(center, rotation);
var result = new BlockGameBlock[positions.Length];
var i = 0;
foreach (var position in positions)
{
result[i++] = position.ToBlockGameBlock(_gameBlockColor);
}
return result;
}
/// <summary>
/// Gets a list of all of the blocks comprising this piece in worldspace.
/// Used to generate the held piece/next piece preview images.
/// </summary>
public readonly BlockGameBlock[] BlocksForPreview()
{
var xOffset = 0;
var yOffset = 0;
foreach (var offset in Offsets)
{
if (offset.X < xOffset)
xOffset = offset.X;
if (offset.Y < yOffset)
yOffset = offset.Y;
}
return Blocks(new Vector2i(-xOffset, -yOffset), BlockGamePieceRotation.North);
}
/// <summary>
/// Generates a game piece for a given type of game piece.
/// See <see cref="BlockGamePieceType"/> for the available options.
/// </summary>
/// <param name="type">The type of game piece to generate.</param>
public static BlockGamePiece GetPiece(BlockGamePieceType type)
{
//switch statement, hardcoded offsets
return type switch
{
BlockGamePieceType.I => new BlockGamePiece
{
Offsets = new[]
{
new Vector2i(0, -1), new Vector2i(0, 0), new Vector2i(0, 1), new Vector2i(0, 2),
},
_gameBlockColor = BlockGameBlock.BlockGameBlockColor.LightBlue,
CanSpin = true
},
BlockGamePieceType.L => new BlockGamePiece
{
Offsets = new[]
{
new Vector2i(0, -1), new Vector2i(0, 0), new Vector2i(0, 1), new Vector2i(1, 1),
},
_gameBlockColor = BlockGameBlock.BlockGameBlockColor.Orange,
CanSpin = true
},
BlockGamePieceType.LInverted => new BlockGamePiece
{
Offsets = new[]
{
new Vector2i(0, -1), new Vector2i(0, 0), new Vector2i(-1, 1),
new Vector2i(0, 1),
},
_gameBlockColor = BlockGameBlock.BlockGameBlockColor.Blue,
CanSpin = true
},
BlockGamePieceType.S => new BlockGamePiece
{
Offsets = new[]
{
new Vector2i(0, -1), new Vector2i(1, -1), new Vector2i(-1, 0),
new Vector2i(0, 0),
},
_gameBlockColor = BlockGameBlock.BlockGameBlockColor.Green,
CanSpin = true
},
BlockGamePieceType.SInverted => new BlockGamePiece
{
Offsets = new[]
{
new Vector2i(-1, -1), new Vector2i(0, -1), new Vector2i(0, 0),
new Vector2i(1, 0),
},
_gameBlockColor = BlockGameBlock.BlockGameBlockColor.Red,
CanSpin = true
},
BlockGamePieceType.T => new BlockGamePiece
{
Offsets = new[]
{
new Vector2i(0, -1),
new Vector2i(-1, 0), new Vector2i(0, 0), new Vector2i(1, 0),
},
_gameBlockColor = BlockGameBlock.BlockGameBlockColor.Purple,
CanSpin = true
},
BlockGamePieceType.O => new BlockGamePiece
{
Offsets = new[]
{
new Vector2i(0, -1), new Vector2i(1, -1), new Vector2i(0, 0),
new Vector2i(1, 0),
},
_gameBlockColor = BlockGameBlock.BlockGameBlockColor.Yellow,
CanSpin = false
},
_ => new BlockGamePiece
{
Offsets = new[]
{
new Vector2i(0, 0)
}
},
};
}
}
}