Skip to content

Commit

Permalink
Worm eating (#69)
Browse files Browse the repository at this point in the history
* values

* Updates the look of all the game entrance menu screens

* Updates the worm to grow when it eats

* Updates for wall offset on the spice creation

* Removes comment

* Adds readme update
  • Loading branch information
MaxEdwards20 authored Apr 10, 2024
1 parent bc2bd24 commit 1f420c1
Show file tree
Hide file tree
Showing 20 changed files with 291 additions and 127 deletions.
15 changes: 8 additions & 7 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -9,28 +9,29 @@ A game of Snake built using C# in the MonoGame framework, themed around everyone
## In Progress

- [ ] Satchel: Pick head, body, and tail texture for the sandworm
- [ ] Caden: Spice generation when we spawn
- [ ] Caden: Periodic spice generation throughout the game
- [ ] Max: Grow the worm on eating food.
- [ ] Satchel: Loading Screen while joining game
- [ ] Max: On collision, sandworm breaks apart and is available as food for other snakes

## Items to Develop

- [ ] Fix the ability to exit the game and come back in. Dean talked about what we need to do in Teams.
- [ ] 3 different animated sprites for the spice - Satchel
- [ ] Sound effects on the death of worm and when food is eaten - Satchel
- [ ] On collision, sandworm breaks apart and is available as food for other snakes
- [ ] Record players score, kills and highest position. Probably can be added to the `GameScores` object.
- [ ] Game over screen with score, kills, and highest position achieved. This is an overlay on the multiplayer game behind it.
- [ ] Particle system for the death of a sandworm
- [ ] Leaderboard to display top 5 players and client's score in corner of game.
- [ ] The new player should join as an invincible entity. Add this functionality and a system to update it after 3 seconds to be removed from the entity.
- [ ] Add a player status in leaderboard to show whether the player is currently invincible.
- [ ] Port Particle System - Satchel
- [ ] Connection View sprite font or visual indicator.
- [ ] Connection View sprite font or visual indicator.
- [ ] Message receiver for the client about collisions that can be used to call the particle system and sound effects.

## Done

- [x] Max: Grow the worm on eating food.
- [x] Satchel: Loading Screen while joining game
- [x] Caden: Spice generation when we spawn
- [x] Caden: Periodic spice generation throughout the game
- [x] Max: Collision Detection system.
- [x] Max: Keyboard support for left, right, up, down, diagonal up left and diagonal up right. Also add these to the wormMovement system.
- [x] Max: Snake Movement with the queue system
Expand All @@ -44,7 +45,7 @@ A game of Snake built using C# in the MonoGame framework, themed around everyone
- [x] Caden: Map generation
- [x] Satchel: How to Play View
- [x] Satchel: Create Name View
- [x] Satchel: Create Connection View
- [x] Satchel: Create Connection View

## Debugging

Expand Down
10 changes: 5 additions & 5 deletions src/Client/GameModel.cs
Original file line number Diff line number Diff line change
Expand Up @@ -24,7 +24,7 @@ public class GameModel
private Systems.Interpolation m_systemInterpolation;
private Systems.Renderer m_renderer;
private Shared.Systems.WormMovement m_systemWormMovement;
private Shared.Systems.CollisionHandler m_systemCollisionHandler;
private Shared.Systems.GrowthHandler m_systemGrowthHandler;
private Controls m_controls;
private GraphicsDeviceManager m_graphics;
private SpriteFont m_font;
Expand All @@ -43,7 +43,7 @@ public void update(TimeSpan elapsedTime)
{
m_systemNetwork.update(elapsedTime, MessageQueueClient.instance.getMessages());
m_systemKeyboardInput.update(elapsedTime);
m_systemCollisionHandler.update(elapsedTime);
m_systemGrowthHandler.update(elapsedTime);
m_systemWormMovement.update(elapsedTime);
m_systemInterpolation.update(elapsedTime);
m_systemCamera.update(elapsedTime);
Expand Down Expand Up @@ -74,7 +74,7 @@ public bool initialize(ContentManager contentManager, Controls controls, Graphic
m_systemCamera = new Systems.Camera(new Vector2(graphics.PreferredBackBufferWidth, graphics.PreferredBackBufferHeight));

m_renderer = new Systems.Renderer(m_systemCamera, graphics, m_font, m_sand);
m_systemCollisionHandler = new Shared.Systems.CollisionHandler();
m_systemGrowthHandler = new Shared.Systems.GrowthHandler();
m_systemWormMovement = new Shared.Systems.WormMovement();
m_systemNetwork = new Systems.Network(m_playerName);

Expand Down Expand Up @@ -186,7 +186,7 @@ private void addEntity(Entity entity)
// NOTE: Update the systems we use here
m_entities[entity.id] = entity;
m_systemKeyboardInput.add(entity);
m_systemCollisionHandler.add(entity);
m_systemGrowthHandler.add(entity);
m_systemWormMovement.add(entity);
m_renderer.add(entity);
m_systemNetwork.add(entity);
Expand All @@ -203,7 +203,7 @@ private void removeEntity(uint id)
// NOTE: Update the systems we use here
m_entities.Remove(id);
m_systemKeyboardInput.remove(id);
m_systemCollisionHandler.remove(id);
m_systemGrowthHandler.remove(id);
m_systemWormMovement.remove(id);
m_systemNetwork.remove(id);
m_renderer.remove(id);
Expand Down
17 changes: 9 additions & 8 deletions src/Client/Menu/ChooseNameView.cs
Original file line number Diff line number Diff line change
Expand Up @@ -74,15 +74,16 @@ public override void render(GameTime gameTime)
m_spriteBatch.Begin();

// Calculate the center position for "Enter Your Name" text
string enterNameText = $"Enter Your Name: [ Using Keyboard ] \n {playerName}";
string enterNameText = $"Enter Your Name: \n {playerName}";
Vector2 textSize = font.MeasureString(enterNameText);
Vector2 textPosition = new Vector2(
(m_graphics.PreferredBackBufferWidth - textSize.X) / 2,
(m_graphics.PreferredBackBufferHeight - textSize.Y) / 2);
(m_graphics.PreferredBackBufferWidth) / 2,
(m_graphics.PreferredBackBufferHeight) / 2);

// Draw "Enter Your Name" text

m_spriteBatch.DrawString(font, enterNameText, textPosition, Colors.displayColor);
Drawing.CustomDrawString(font, enterNameText, textPosition, Colors.displayColor, m_spriteBatch, true, true, scale:.8f);
// m_spriteBatch.DrawString(font, enterNameText, textPosition, Colors.displayColor);


// Draw "Press Enter to proceed" below the name text if a name has been entered
Expand All @@ -91,11 +92,11 @@ public override void render(GameTime gameTime)
string proceedText = "Press Enter to proceed";
Vector2 proceedTextSize = font.MeasureString(proceedText);
Vector2 proceedTextPosition = new Vector2(
(m_graphics.PreferredBackBufferWidth - proceedTextSize.X) / 2,
textPosition.Y + textSize.Y + 20); // 20 pixels below the name text
textPosition.X,
textPosition.Y + 90); // 20 pixels below the name text


m_spriteBatch.DrawString(font, proceedText, proceedTextPosition, Colors.displayColor);
Drawing.CustomDrawString(font, proceedText, proceedTextPosition, Colors.displayColor, m_spriteBatch, true, false, scale:.6f);
// m_spriteBatch.DrawString(font, proceedText, proceedTextPosition, Colors.displayColor);
}

m_spriteBatch.End();
Expand Down
4 changes: 2 additions & 2 deletions src/Client/Menu/ConnectingView.cs
Original file line number Diff line number Diff line change
Expand Up @@ -12,7 +12,7 @@ public class ConnectingView : GameStateView
private SpriteFont font;
private string connectingMessage = "Connecting to Server";
private bool isConnected = false;
private double elapsedTimeSinceLastAttempt = 0;
private double elapsedTimeSinceLastAttempt = 1500; // Start at 1500 so we only need to wait 500ms before first attempt
private const double attemptInterval = 2000; // Attempt to connect every 2 seconds
private double periodUpdateTime = 500; // Update period for visual

Expand Down Expand Up @@ -51,7 +51,7 @@ public override void render(GameTime gameTime)
m_spriteBatch.Begin();
Vector2 position = new Vector2(m_graphics.PreferredBackBufferWidth / 2, m_graphics.PreferredBackBufferHeight / 2);
Vector2 origin = font.MeasureString(connectingMessage) / 2;
m_spriteBatch.DrawString(font, connectingMessage, position - origin, Colors.displayColor);
Drawing.CustomDrawString(font, connectingMessage, position, Colors.displayColor, m_spriteBatch, true, true, true);
m_spriteBatch.End();
}

Expand Down
41 changes: 3 additions & 38 deletions src/Client/Menu/GamePlayView.cs
Original file line number Diff line number Diff line change
Expand Up @@ -16,11 +16,9 @@ namespace Client.Menu
public class GamePlayView : GameStateView
{
private ContentManager m_contentManager;
private bool m_isSetup;
private bool m_isKeyboardRegistered;
private MenuStateEnum m_newState;
private GameModel m_gameModel;
private TimeSpan m_connectToServerTime = TimeSpan.Zero;
private Controls m_controls;
private StringBuilder playerName;

Expand All @@ -34,7 +32,6 @@ public override void initialize()
{
m_gameModel = new GameModel(playerName);
m_gameModel.initialize(m_contentManager, m_controls, m_graphics);
m_isSetup = false;
m_isKeyboardRegistered = false;
m_newState = MenuStateEnum.GamePlay;
}
Expand All @@ -50,38 +47,12 @@ public override MenuStateEnum processInput(GameTime gameTime)
RegisterCommands();
m_isKeyboardRegistered = true;
}

//if (!m_isSetup)
//{
// setup(gameTime);
//}


MenuKeyboardInput.Update(gameTime); // essentially just checking for whether we have escaped to the main menu
if (m_newState != MenuStateEnum.GamePlay){return handleSwitchToMainMenu();}
return MenuStateEnum.GamePlay;
}

//private void setup(GameTime gameTime)
//{
// if (m_connectToServerTime == TimeSpan.Zero)
// {
// m_connectToServerTime = TimeSpan.FromSeconds(2); // Try to connect every 2 seconds
// var res = connectToServer();
// if (res)
// {
// m_isSetup = true;
// }
// }
// else
// {
// m_connectToServerTime -= gameTime.ElapsedGameTime;
// if (m_connectToServerTime <= TimeSpan.Zero)
// {
// m_connectToServerTime = TimeSpan.Zero;
// }
// }
//}


public override void update(GameTime gameTime)
{
m_gameModel.update(gameTime.ElapsedGameTime);
Expand All @@ -97,12 +68,7 @@ public override void RegisterCommands()
{
MenuKeyboardInput.registerCommand(MenuKeyboardInput.Escape, true, escape);
}

//private bool connectToServer()
//{
// return MessageQueueClient.instance.initialize("localhost", 3000);
//}


private void escape(GameTime gameTime, float scale)
{
m_newState = MenuStateEnum.MainMenu;
Expand All @@ -111,7 +77,6 @@ private void escape(GameTime gameTime, float scale)
private MenuStateEnum handleSwitchToMainMenu()
{
MenuKeyboardInput.ClearAllCommands();
m_isSetup = false;
var temp = m_newState;
m_newState = MenuStateEnum.GamePlay;
try
Expand Down
41 changes: 29 additions & 12 deletions src/Client/Menu/HowToPlay.cs
Original file line number Diff line number Diff line change
Expand Up @@ -8,10 +8,11 @@ namespace Client.Menu
public class HowToPlayView : GameStateView
{
private SpriteFont font;

private string howToPlayMessage =
"Control a snake to eat food and grow. Use arrow keys for movement. \n" +
"(Custom controls in Main Menu) \n" +
"Avoid wall and other players!. How long can you grow? Try to beat the high score!";
"Control a worm to eat spice and grow.\nUse configured keys for movement." +
"\nAvoid walls and other players!\nTry to beat the high score!" +
"\n(Custom controls in Main Menu)\n";
private string titleMessage = "HOW TO PLAY";
private string continueMessage = "Press Enter to continue";
private KeyboardState oldState;
Expand All @@ -34,6 +35,12 @@ public override MenuStateEnum processInput(GameTime gameTime)
KeyboardState newState = Keyboard.GetState();

timeSinceLastEnterPress += gameTime.ElapsedGameTime.TotalMilliseconds;

// Check for Escape key press to return to MainMenu
if (newState.IsKeyDown(Keys.Escape))
{
return MenuStateEnum.Controls; // Immediately return to MainMenu when Escape is pressed
}

// Proceed to the next game state if the player presses Enter and enough time has passed since the last Enter press
if (newState.IsKeyDown(Keys.Enter) && oldState.IsKeyUp(Keys.Enter) && timeSinceLastEnterPress >= enterKeyDelay)
Expand All @@ -60,30 +67,40 @@ public override void render(GameTime gameTime)
m_spriteBatch.Begin();

// Define text scale
Vector2 textScale = new Vector2(0.5f, 0.5f);
Vector2 textScale = new Vector2(0.5f, 0.5f);

// Background Rectangle
var recPosition = new Vector2(m_graphics.PreferredBackBufferWidth / 5 - 20,
m_graphics.PreferredBackBufferHeight / 4 - 50);
Drawing.DrawBlurredRectangle(m_spriteBatch, recPosition, new Vector2(700, 400), 5, 0.6f);


// Title
Vector2 titlePosition = new Vector2(m_graphics.PreferredBackBufferWidth / 2, m_graphics.PreferredBackBufferHeight / 4);
Vector2 titleOrigin = font.MeasureString(titleMessage) / 2;
m_spriteBatch.DrawString(font, titleMessage, titlePosition - (titleOrigin * textScale), Colors.displayColor, 0f, Vector2.Zero, textScale, SpriteEffects.None, 0f);


Vector2 titleOrigin = font.MeasureString(titleMessage) / 2;
Drawing.CustomDrawString(font, titleMessage, titlePosition, Colors.displayColor, m_spriteBatch, true, false, scale: 1.0f);
// m_spriteBatch.DrawString(font, titleMessage, titlePosition - (titleOrigin * textScale), Colors.displayColor, 0f, Vector2.Zero, textScale, SpriteEffects.None, 0f);

// How to Play Instructions
Vector2 instructionsPosition = new Vector2(m_graphics.PreferredBackBufferWidth / 2, m_graphics.PreferredBackBufferHeight / 2.5f);
Vector2 instructionsPosition = new Vector2(m_graphics.PreferredBackBufferWidth / 5, m_graphics.PreferredBackBufferHeight / 2.5f);
string[] lines = howToPlayMessage.Split('\n');
foreach (string line in lines)
{
Vector2 lineSize = font.MeasureString(line) * textScale;

m_spriteBatch.DrawString(font, line, instructionsPosition - new Vector2(lineSize.X / 2, 0), Colors.displayColor, 0f, Vector2.Zero, textScale, SpriteEffects.None, 0f);
instructionsPosition.Y += lineSize.Y + 5; // Adjust spacing between lines if necessary, taking scale into account
Drawing.CustomDrawString(font, line, instructionsPosition,
Colors.displayColor, m_spriteBatch, false, false, scale: 0.75f);
// m_spriteBatch.DrawString(font, line, instructionsPosition - new Vector2(lineSize.X / 2, 0), Colors.displayColor, 0f, Vector2.Zero, textScale, SpriteEffects.None, 0f);
instructionsPosition.Y += lineSize.Y + 20; // Adjust spacing between lines if necessary, taking scale into account
}

// Continue Prompt
Vector2 continuePosition = new Vector2(m_graphics.PreferredBackBufferWidth / 2, (m_graphics.PreferredBackBufferHeight / 4) * 3);
Vector2 continuePosition = new Vector2(m_graphics.PreferredBackBufferWidth / 2, (m_graphics.PreferredBackBufferHeight / 4) * 3 + 50);
Vector2 continueOrigin = font.MeasureString(continueMessage) / 2;

m_spriteBatch.DrawString(font, continueMessage, continuePosition - (continueOrigin * textScale), Colors.displayColor, 0f, Vector2.Zero, textScale, SpriteEffects.None, 0f);
Drawing.CustomDrawString( font, continueMessage, continuePosition, Colors.displayColor, m_spriteBatch, true, true, scale: 1f);
// m_spriteBatch.DrawString(font, continueMessage, continuePosition - (continueOrigin * textScale), Colors.displayColor, 0f, Vector2.Zero, textScale, SpriteEffects.None, 0f);


m_spriteBatch.End();
Expand Down
18 changes: 16 additions & 2 deletions src/Client/Systems/Network.cs
Original file line number Diff line number Diff line change
Expand Up @@ -162,8 +162,8 @@ private void handleConnectAck(TimeSpan elapsedTime, ConnectAck message, string n
/// actually has the entity, and if it does, updates the components
/// that are in common between the message and the entity.
/// </summary>
private void handleUpdateEntity(TimeSpan elapsedTime, UpdateEntity message)
{
private void handleUpdateEntity(TimeSpan elapsedTime, UpdateEntity message)
{
if (m_entities.ContainsKey(message.id))
{
var entity = m_entities[message.id];
Expand Down Expand Up @@ -191,7 +191,21 @@ private void handleUpdateEntity(TimeSpan elapsedTime, UpdateEntity message)
{
entity.get<SpicePower>().setPower(message.spicePower);
}
if (entity.contains<ParentId>() && message.hasParent)
{
entity.remove<ParentId>();
entity.add(new ParentId(message.parentId));
// NOTE: This would trigger an update of everyone's anchor points

}
if (entity.contains<ChildId>() && message.hasChild)
{
entity.remove<ChildId>();
entity.add(new ChildId(message.childId));
// NOTE: This would trigger an update of everyone's anchor points
}
}

}
}
}
25 changes: 12 additions & 13 deletions src/Client/Systems/Renderer.cs
Original file line number Diff line number Diff line change
Expand Up @@ -11,6 +11,7 @@
using Client.Components;
using Client.Menu;
using System.Runtime.CompilerServices;
using Shared.Systems;

namespace Client.Systems;

Expand Down Expand Up @@ -67,31 +68,29 @@ public void render(TimeSpan elapsedTime, SpriteBatch spriteBatch)
);

var heads = new List<Entity>();
var bodies = new List<Entity>();
var tails = new List<Entity>();
var others = new List<Entity>();

foreach (Entity entity in m_entities.Values)
{
if (entity.contains<Head>())
heads.Add(entity);
else if (entity.contains<Tail>())
tails.Add(entity);
else if (entity.contains<Worm>())
bodies.Add(entity);
continue;
else
others.Add(entity);
}

foreach (Entity entity in others)
renderEntity(elapsedTime, spriteBatch, entity);
foreach (Entity entity in tails)
renderEntity(elapsedTime, spriteBatch, entity);
foreach (Entity entity in bodies)
renderEntity(elapsedTime, spriteBatch, entity);
foreach (Entity entity in heads)
renderEntity(elapsedTime, spriteBatch, entity);

// We want to sort bodies by their position in the worm

foreach (Entity head in heads)
{
var worm = WormMovement.getWormFromHead(head, m_entities);
for (int i = worm.Count - 1; i >= 0; i--)
renderEntity(elapsedTime, spriteBatch, worm[i]);
}
spriteBatch.End();
}

Expand Down
Loading

0 comments on commit 1f420c1

Please sign in to comment.