diff --git a/PolygonBazooka/Content/Content.mgcb b/PolygonBazooka/Content/Content.mgcb index c765da6..9ba38f5 100644 --- a/PolygonBazooka/Content/Content.mgcb +++ b/PolygonBazooka/Content/Content.mgcb @@ -13,6 +13,13 @@ #---------------------------------- Content ---------------------------------# +#begin Fonts/GameOver.spritefont +/importer:FontDescriptionImporter +/processor:FontDescriptionProcessor +/processorParam:PremultiplyAlpha=True +/processorParam:TextureFormat=Compressed +/build:Fonts/GameOver.spritefont + #begin Textures/blue_shadow.png /importer:TextureImporter /processor:TextureProcessor diff --git a/PolygonBazooka/DiscordRichPresence.cs b/PolygonBazooka/DiscordRichPresence.cs index bc03874..d57ed3e 100644 --- a/PolygonBazooka/DiscordRichPresence.cs +++ b/PolygonBazooka/DiscordRichPresence.cs @@ -1,3 +1,4 @@ +using System; using DiscordRPC; using DiscordRPC.Message; @@ -40,9 +41,8 @@ private void OnReady(object sender, ReadyMessage args) _client.SetPresence(_presence); } - - // TODO: Implement UpdateStatus method - public void UpdateStatus() + + public void UpdateStatus(GameState state) { if (_client == null) return; @@ -52,5 +52,26 @@ public void UpdateStatus() if (_client.CurrentPresence == null) return; + + switch (state) + { + case GameState.MainMenu: + _client.UpdateDetails("In the Menu"); + _client.UpdateState("Existing"); + break; + + case GameState.Playing: + _client.UpdateDetails("Stacking blocks"); + _client.UpdateState("Playing Solo"); + break; + + case GameState.SoloGameOver: + _client.UpdateDetails("Topped out"); + _client.UpdateState("Game Over"); + break; + + default: + throw new ArgumentOutOfRangeException(nameof(state), state, null); + } } } \ No newline at end of file diff --git a/PolygonBazooka/Elements/Player.cs b/PolygonBazooka/Elements/Player.cs index 7409d05..421037e 100644 --- a/PolygonBazooka/Elements/Player.cs +++ b/PolygonBazooka/Elements/Player.cs @@ -62,8 +62,12 @@ public class Player : DrawableGameComponent public bool Failed; - public Player(Game game, bool localPlayer) : base(game) + private readonly PolygonBazookaGame _game; + + public Player(PolygonBazookaGame game, bool localPlayer) : base(game) { + _game = game; + _board = new TileType[Const.Rows, Const.Cols]; _clearingTiles = new(); @@ -114,7 +118,7 @@ public override void Draw(GameTime gameTime) // TODO: make the sprites scale based on the window size _spriteBatch.Draw(_boardTexture, new Rectangle((int)RenderPosition.X, (int)RenderPosition.Y, - (int)(_boardTexture.Width * Const.Scale), (int)(_boardTexture.Height * Const.Scale)), Color.White); + (int)(_boardTexture.Width * _game.Scale), (int)(_boardTexture.Height * _game.Scale)), Color.White); for (int row = 0; row < Const.Rows; row++) { @@ -123,8 +127,8 @@ public override void Draw(GameTime gameTime) if (_board[row, col] == TileType.Empty) continue; - int x = (int)(RenderPosition.X + col * (16 * Const.Scale) + 4 * Const.Scale); - int y = (int)(RenderPosition.Y + row * (16 * Const.Scale) + 4 * Const.Scale); + int x = (int)(RenderPosition.X + col * (16 * _game.Scale) + 4 * _game.Scale); + int y = (int)(RenderPosition.Y + row * (16 * _game.Scale) + 4 * _game.Scale); RenderTile(_board[row, col], x, y); } } @@ -136,9 +140,9 @@ public override void Draw(GameTime gameTime) if (_yOrigin < _yOrbit) shadowOffset = -1; - int shadowX = (int)(RenderPosition.X + _xOrigin * (16 * Const.Scale) + 4 * Const.Scale); - int shadowY = (int)(RenderPosition.Y + (GetLowestEmptyCell(_xOrigin) + shadowOffset) * (16 * Const.Scale) - + 4 * Const.Scale); + int shadowX = (int)(RenderPosition.X + _xOrigin * (16 * _game.Scale) + 4 * _game.Scale); + int shadowY = (int)(RenderPosition.Y + (GetLowestEmptyCell(_xOrigin) + shadowOffset) * (16 * _game.Scale) + + 4 * _game.Scale); RenderTile(_fallingBlockOrigin, shadowX, shadowY, true); } @@ -149,51 +153,51 @@ public override void Draw(GameTime gameTime) if (_yOrigin > _yOrbit) shadowOffset = -1; - int shadowX = (int)(RenderPosition.X + _xOrbit * (16 * Const.Scale) + 4 * Const.Scale); - int shadowY = (int)(RenderPosition.Y + (GetLowestEmptyCell(_xOrbit) + shadowOffset) * (16 * Const.Scale) - + 4 * Const.Scale); + int shadowX = (int)(RenderPosition.X + _xOrbit * (16 * _game.Scale) + 4 * _game.Scale); + int shadowY = (int)(RenderPosition.Y + (GetLowestEmptyCell(_xOrbit) + shadowOffset) * (16 * _game.Scale) + + 4 * _game.Scale); RenderTile(_fallingBlockOrbit, shadowX, shadowY, true); } if (_fallingBlockOrigin != TileType.Empty) { - int tileX = (int)(RenderPosition.X + _xOrigin * (16 * Const.Scale) + 4 * Const.Scale); - int tileY = (int)(RenderPosition.Y + _yOrigin * (16 * Const.Scale) + 4 * Const.Scale); + int tileX = (int)(RenderPosition.X + _xOrigin * (16 * _game.Scale) + 4 * _game.Scale); + int tileY = (int)(RenderPosition.Y + _yOrigin * (16 * _game.Scale) + 4 * _game.Scale); RenderTile(_fallingBlockOrigin, tileX, tileY); } if (_fallingBlockOrbit != TileType.Empty) { - int tileX = (int)(RenderPosition.X + _xOrbit * (16 * Const.Scale) + 4 * Const.Scale); - int tileY = (int)(RenderPosition.Y + _yOrbit * (16 * Const.Scale) + 4 * Const.Scale); + int tileX = (int)(RenderPosition.X + _xOrbit * (16 * _game.Scale) + 4 * _game.Scale); + int tileY = (int)(RenderPosition.Y + _yOrbit * (16 * _game.Scale) + 4 * _game.Scale); RenderTile(_fallingBlockOrbit, tileX, tileY); } if (_nextBlockOrigin != TileType.Empty) { - int x = (int)(RenderPosition.X + 7 * (16 * Const.Scale) + 8 * Const.Scale); - int y = (int)(RenderPosition.Y + 0 * (16 * Const.Scale) + 14 * Const.Scale); + int x = (int)(RenderPosition.X + 7 * (16 * _game.Scale) + 8 * _game.Scale); + int y = (int)(RenderPosition.Y + 0 * (16 * _game.Scale) + 14 * _game.Scale); RenderTile(_nextBlockOrigin, x, y); } if (_nextBlockOrbit != TileType.Empty) { - int x = (int)(RenderPosition.X + 7 * (16 * Const.Scale) + 8 * Const.Scale); - int y = (int)(RenderPosition.Y + 1 * (16 * Const.Scale) + 14 * Const.Scale); + int x = (int)(RenderPosition.X + 7 * (16 * _game.Scale) + 8 * _game.Scale); + int y = (int)(RenderPosition.Y + 1 * (16 * _game.Scale) + 14 * _game.Scale); RenderTile(_nextBlockOrbit, x, y); } if (_nextNextBlockOrigin != TileType.Empty) { - int x = (int)(RenderPosition.X + 7 * (16 * Const.Scale) + 8 * Const.Scale); - int y = (int)(RenderPosition.Y + 2 * (16 * Const.Scale) + 18 * Const.Scale); + int x = (int)(RenderPosition.X + 7 * (16 * _game.Scale) + 8 * _game.Scale); + int y = (int)(RenderPosition.Y + 2 * (16 * _game.Scale) + 18 * _game.Scale); RenderTile(_nextNextBlockOrigin, x, y); } if (_nextNextBlockOrbit != TileType.Empty) { - int x = (int)(RenderPosition.X + 7 * (16 * Const.Scale) + 8 * Const.Scale); - int y = (int)(RenderPosition.Y + 3 * (16 * Const.Scale) + 18 * Const.Scale); + int x = (int)(RenderPosition.X + 7 * (16 * _game.Scale) + 8 * _game.Scale); + int y = (int)(RenderPosition.Y + 3 * (16 * _game.Scale) + 18 * _game.Scale); RenderTile(_nextNextBlockOrbit, x, y); } @@ -202,10 +206,10 @@ public override void Draw(GameTime gameTime) foreach (Vector2 tile in _clearingTiles) { - int x = (int)(RenderPosition.X + tile.X * (16 * Const.Scale) - 12 * Const.Scale); - int y = (int)(RenderPosition.Y + tile.Y * (16 * Const.Scale) - 12 * Const.Scale); + int x = (int)(RenderPosition.X + tile.X * (16 * _game.Scale) - 12 * _game.Scale); + int y = (int)(RenderPosition.Y + tile.Y * (16 * _game.Scale) - 12 * _game.Scale); _spriteBatch.Draw(_clearAnimationAtlas.GetRegion(_clearAnimationIndex), new Rectangle(x, y, - (int)(48 * Const.Scale), (int)(48 * Const.Scale)), Color.White); + (int)(48 * _game.Scale), (int)(48 * _game.Scale)), Color.White); } _spriteBatch.End(); @@ -234,7 +238,7 @@ private void RenderTile(TileType type, int x, int y, bool shadow = false) if (texture != null) { _spriteBatch.Draw(texture, new Rectangle(x, y, - (int)(texture.Width * Const.Scale), (int)(texture.Height * Const.Scale)), Color.White); + (int)(texture.Width * _game.Scale), (int)(texture.Height * _game.Scale)), Color.White); } } @@ -267,6 +271,9 @@ private Texture2D GetShadowTexture(TileType type) public void HardDrop() { + if (IsClearing()) + return; + // drop origin first if lower // they are flipped and i have no idea why but it works so.. if (_yOrigin <= _yOrbit) @@ -333,7 +340,7 @@ private void DropPiece(bool origin, int destY) } } - private bool IsClearing() + public bool IsClearing() { return DateTimeOffset.Now.ToUnixTimeMilliseconds() - LastClear < ClearTime; } @@ -389,6 +396,9 @@ public void MoveRightFully() public void MoveDown() { + if (IsClearing()) + return; + int originLowestEmptyCell = GetLowestEmptyCell(_xOrigin); int orbitLowestEmptyCell = GetLowestEmptyCell(_xOrbit); diff --git a/PolygonBazooka/PolygonBazookaGame.cs b/PolygonBazooka/PolygonBazookaGame.cs index 87a4374..2bdd6bc 100644 --- a/PolygonBazooka/PolygonBazookaGame.cs +++ b/PolygonBazooka/PolygonBazookaGame.cs @@ -10,8 +10,9 @@ public enum GameState { MainMenu, Playing, + SoloGameOver, } - + public class PolygonBazookaGame : Game { private readonly ScreenManager _screenManager = new(); @@ -19,6 +20,14 @@ public class PolygonBazookaGame : Game public readonly DiscordRichPresence DiscordRpc = new(); + // playing for now, until a menu is created + public GameState State { get; private set; } = GameState.Playing; + + public float Scale { get; private set; } = 1; + + private int _lastWindowWidth; + private int _lastWindowHeight; + public PolygonBazookaGame() { var graphics = new GraphicsDeviceManager(this); @@ -42,10 +51,11 @@ protected override void Initialize() base.Initialize(); } - + public void ChangeGameState(GameState newState) { - // TODO: implement + State = newState; + DiscordRpc.UpdateStatus(newState); } protected override void LoadContent() @@ -65,6 +75,13 @@ protected override void Update(GameTime gameTime) Keyboard.GetState().IsKeyDown(Keys.Escape)) Exit(); + if (_lastWindowWidth != Window.ClientBounds.Width || _lastWindowHeight != Window.ClientBounds.Height) + { + Scale = (float)Window.ClientBounds.Height / 300; + _lastWindowWidth = Window.ClientBounds.Width; + _lastWindowHeight = Window.ClientBounds.Height; + } + base.Update(gameTime); } diff --git a/PolygonBazooka/Screens/PlayingScreen.cs b/PolygonBazooka/Screens/PlayingScreen.cs index 333c461..5392245 100644 --- a/PolygonBazooka/Screens/PlayingScreen.cs +++ b/PolygonBazooka/Screens/PlayingScreen.cs @@ -5,9 +5,11 @@ using MonoGame.Extended.Screens; using PolygonBazooka.Elements; +// ReSharper disable PossibleLossOfFraction + namespace PolygonBazooka.Screens; -public class PlayingScreen(Game game) : GameScreen(game) +public class PlayingScreen(PolygonBazookaGame game) : GameScreen(game) { private SpriteBatch _spriteBatch; private Player _localPlayer; @@ -19,6 +21,9 @@ public class PlayingScreen(Game game) : GameScreen(game) private bool _flipPressed; private bool _hardDropPressed; + private bool _retryPressed; + private long _retryPressStart; + private bool _leftDasActive; private bool _rightDasActive; @@ -35,13 +40,17 @@ public class PlayingScreen(Game game) : GameScreen(game) public float AutoRepeatRate = 0; public float SoftDropRate = 100; + // render player at the centre of screen and adjust size based on it + private int _lastWindowWidth; + private int _lastWindowHeight; + public override void LoadContent() { _spriteBatch = new(Game.GraphicsDevice); - _localPlayer = new(Game, true) + _localPlayer = new(game, true) { - RenderPosition = new(100, 150), + RenderPosition = new(_lastWindowWidth / 2 - 78 * game.Scale, _lastWindowHeight / 2 - 78 * game.Scale), }; base.LoadContent(); @@ -53,7 +62,26 @@ public override void Update(GameTime gameTime) if (_localPlayer.Failed) { - // TODO: implement game over thing + game.ChangeGameState(GameState.SoloGameOver); + + if (keyboardState.IsKeyDown(Keys.R)) + { + if (!_retryPressed) + _retryPressStart = DateTimeOffset.Now.ToUnixTimeMilliseconds(); + + _retryPressed = true; + + if (DateTimeOffset.Now.ToUnixTimeMilliseconds() - _retryPressStart >= 1000) + { + _localPlayer = new(game, true) + { + RenderPosition = new(_lastWindowWidth / 2 - 78 * game.Scale, _lastWindowHeight / 2 - 78 * game.Scale), + }; + } + } + + if (keyboardState.IsKeyUp(Keys.R) && _retryPressed) + _retryPressed = false; } else { @@ -173,13 +201,32 @@ public override void Update(GameTime gameTime) _localPlayer.MoveDown(); } - _localPlayer.ProcessGravity(); + if (!_localPlayer.IsClearing()) + _localPlayer.ProcessGravity(); + _localPlayer.Clear(); } + + if (_lastWindowHeight != Game.Window.ClientBounds.Height || _lastWindowWidth != Game.Window.ClientBounds.Width) + { + _lastWindowWidth = Game.Window.ClientBounds.Width; + _lastWindowHeight = Game.Window.ClientBounds.Height; + + _localPlayer.RenderPosition = new(_lastWindowWidth / 2 - 78 * game.Scale, + _lastWindowHeight / 2 - 78 * game.Scale); + } } public override void Draw(GameTime gameTime) { _localPlayer.Draw(gameTime); + + if (_localPlayer.Failed) + { + _spriteBatch.Begin(); + _spriteBatch.DrawString(Game.Content.Load("Fonts/GameOver"), "Game Over. Hold R to retry", + new(50, 50), Color.Red); + _spriteBatch.End(); + } } } \ No newline at end of file