Skip to content

Commit

Permalink
Collision detection (#54)
Browse files Browse the repository at this point in the history
* Updates README

* updates the name view

* Adds collision handler everywhere in the code

* Everything still working

* Sets up message transmission well

* Adds wall generation

* Adds wall texture
  • Loading branch information
MaxEdwards20 authored Apr 9, 2024
1 parent 3881ccf commit d072166
Show file tree
Hide file tree
Showing 21 changed files with 363 additions and 48 deletions.
7 changes: 4 additions & 3 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -12,15 +12,14 @@ A game of Snake built using C# in the MonoGame framework, themed around everyone
- [ ] Caden: Map generation
- [ ] Caden: Spice generation when we spawn
- [ ] Caden: Periodic spice generation throughout the game
- [ ] Max: Keyboard support for left, right, up, down, diagonal up left and diagonal up right. Also add these to the wormMovement system.
- [ ] Menu Screen to let player name themselves (probably similar to how control selection screen will work) - Satchel

- [ ] Max: Collision detection. Know whether we hit spice or another sandworm

## Items to Develop

- [ ] Fix 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
- [ ] Sound effects on death of worm and when food is eaten - Satchel
- [ ] Collision detection. Know whether we hit spice or another sandworm
- [ ] 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.
Expand All @@ -30,6 +29,8 @@ A game of Snake built using C# in the MonoGame framework, themed around everyone
- [ ] Add a player status in leaderboard to show whether the player is currently invincible.

## Done

- [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
- [x] Max: Upgrade our movement system to reduce the lag in rotation
- [x] Max: Add name support for the player
Expand Down
12 changes: 12 additions & 0 deletions src/Client/Content/Content.mgcb
Original file line number Diff line number Diff line change
Expand Up @@ -159,3 +159,15 @@
/processorParam:TextureFormat=Color
/build:Textures/tail.png


#begin Textures/wall.png
/importer:TextureImporter
/processor:TextureProcessor
/processorParam:ColorKeyColor=255,0,255,255
/processorParam:ColorKeyEnabled=True
/processorParam:GenerateMipmaps=False
/processorParam:PremultiplyAlpha=True
/processorParam:ResizeToPowerOfTwo=False
/processorParam:MakeSquare=False
/processorParam:TextureFormat=Color
/build:Textures/wall.png
Binary file added src/Client/Content/Textures/wall.png
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
10 changes: 10 additions & 0 deletions src/Client/GameModel.cs
Original file line number Diff line number Diff line change
Expand Up @@ -23,6 +23,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 Controls m_controls;
private GraphicsDeviceManager m_graphics;
private SpriteFont m_font;
Expand All @@ -35,6 +36,7 @@ public void update(TimeSpan elapsedTime)
{
m_systemNetwork.update(elapsedTime, MessageQueueClient.instance.getMessages());
m_systemKeyboardInput.update(elapsedTime);
m_systemCollisionHandler.update(elapsedTime);
m_systemWormMovement.update(elapsedTime);
m_systemInterpolation.update(elapsedTime);
m_systemCamera.update(elapsedTime);
Expand Down Expand Up @@ -65,6 +67,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_systemWormMovement = new Shared.Systems.WormMovement();
m_systemNetwork = new Systems.Network();

Expand Down Expand Up @@ -120,6 +123,11 @@ private Entity createEntity(Shared.Messages.NewEntity message)
{
entity.add(new Collision());
}

if (message.hasWall)
{
entity.add(new Shared.Components.Wall());
}

// Worm parts

Expand Down Expand Up @@ -171,6 +179,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_systemWormMovement.add(entity);
m_renderer.add(entity);
m_systemNetwork.add(entity);
Expand All @@ -187,6 +196,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_systemWormMovement.remove(id);
m_systemNetwork.remove(id);
m_renderer.remove(id);
Expand Down
4 changes: 2 additions & 2 deletions src/Client/Menu/ChooseNameView.cs
Original file line number Diff line number Diff line change
Expand Up @@ -82,7 +82,7 @@ public override void render(GameTime gameTime)
(m_graphics.PreferredBackBufferHeight - textSize.Y) / 2);

// Draw "Enter Your Name" text
m_spriteBatch.DrawString(font, enterNameText, textPosition, Color.PaleGoldenrod);
m_spriteBatch.DrawString(font, enterNameText, textPosition, Colors.displayColor);

// Draw "Press Enter to proceed" below the name text if a name has been entered
if (playerName.Length > 0)
Expand All @@ -93,7 +93,7 @@ public override void render(GameTime gameTime)
(m_graphics.PreferredBackBufferWidth - proceedTextSize.X) / 2,
textPosition.Y + textSize.Y + 20); // 20 pixels below the name text

m_spriteBatch.DrawString(font, proceedText, proceedTextPosition, Color.PaleGoldenrod);
m_spriteBatch.DrawString(font, proceedText, proceedTextPosition, Colors.displayColor);
}

m_spriteBatch.End();
Expand Down
6 changes: 3 additions & 3 deletions src/Client/Menu/HowToPlay.cs
Original file line number Diff line number Diff line change
Expand Up @@ -65,22 +65,22 @@ public override void render(GameTime gameTime)
// 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), Color.PaleGoldenrod, 0f, Vector2.Zero, textScale, SpriteEffects.None, 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);
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), Color.PaleGoldenrod, 0f, Vector2.Zero, textScale, SpriteEffects.None, 0f);
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
}

// Continue Prompt
Vector2 continuePosition = new Vector2(m_graphics.PreferredBackBufferWidth / 2, (m_graphics.PreferredBackBufferHeight / 4) * 3);
Vector2 continueOrigin = font.MeasureString(continueMessage) / 2;
m_spriteBatch.DrawString(font, continueMessage, continuePosition - (continueOrigin * textScale), Color.PaleGoldenrod, 0f, Vector2.Zero, textScale, SpriteEffects.None, 0f);
m_spriteBatch.DrawString(font, continueMessage, continuePosition - (continueOrigin * textScale), Colors.displayColor, 0f, Vector2.Zero, textScale, SpriteEffects.None, 0f);

m_spriteBatch.End();
}
Expand Down
10 changes: 0 additions & 10 deletions src/Client/Systems/CollisionDetection.cs

This file was deleted.

5 changes: 5 additions & 0 deletions src/Client/Systems/Network.cs
Original file line number Diff line number Diff line change
Expand Up @@ -52,6 +52,7 @@ public Network() :
{
m_removeEntityHandler((RemoveEntity)message);
});

}

// Have to implement this because it is abstract in the base class
Expand Down Expand Up @@ -187,6 +188,10 @@ private void handleUpdateEntity(TimeSpan elapsedTime, UpdateEntity message)

m_updatedEntities.Add(entity.id);
}
if (entity.contains<SpicePower>() && message.hasSpicePower)
{
entity.get<SpicePower>().setPower(message.spicePower);
}
}
}
}
Expand Down
52 changes: 46 additions & 6 deletions src/Server/GameModel.cs
Original file line number Diff line number Diff line change
@@ -1,5 +1,6 @@

using Microsoft.Xna.Framework;
using Server.Systems;
using Shared.Components;
using Shared.Components.Appearance;
using Shared.Entities;
Expand All @@ -14,7 +15,10 @@ public class GameModel
private Dictionary<uint, Entity> m_entities = new Dictionary<uint, Entity>();
private Dictionary<int, uint> m_clientToEntityId = new Dictionary<int, uint>();
private WormMovement m_systemWormMovement = new WormMovement();
private CollisionDetection m_systemCollisionDetection = new CollisionDetection();
private CollisionHandler m_systemCollisionHandler = new CollisionHandler();
Systems.Network m_systemNetwork = new Server.Systems.Network();
private int mapSize = 5000;

/// <summary>
/// This is where the server-side simulation takes place. Messages
Expand All @@ -24,6 +28,8 @@ public class GameModel
public void update(TimeSpan elapsedTime)
{
m_systemNetwork.update(elapsedTime, MessageQueueServer.instance.getMessages());

Check warning on line 30 in src/Server/GameModel.cs

View workflow job for this annotation

GitHub Actions / buildProject

Possible null reference argument for parameter 'messages' in 'void Network.update(TimeSpan elapsedTime, Queue<Tuple<int, Message>> messages)'.
m_systemCollisionDetection.update(elapsedTime);
m_systemCollisionHandler.update(elapsedTime);
m_systemWormMovement.update(elapsedTime);
}

Expand All @@ -32,14 +38,16 @@ public void update(TimeSpan elapsedTime)
/// </summary>
public bool initialize()
{
generateWalls();
m_systemNetwork.registerJoinHandler(handleJoin);
m_systemNetwork.registerDisconnectHandler(handleDisconnect);

MessageQueueServer.instance.registerConnectHandler(handleConnect);

m_systemCollisionDetection.registerRemoveEntity(removeEntity);
return true;
}



/// <summary>
/// Give everything a chance to gracefully shutdown.
/// </summary>
Expand Down Expand Up @@ -68,13 +76,11 @@ private void handleConnect(int clientId)
private void handleDisconnect(int clientId)
{
m_clients.Remove(clientId);

Message message = new Shared.Messages.RemoveEntity(m_clientToEntityId[clientId]);
MessageQueueServer.instance.broadcastMessage(message);

removeEntity(m_clientToEntityId[clientId]);

m_clientToEntityId.Remove(clientId);

}

/// <summary>
Expand All @@ -91,6 +97,8 @@ private void addEntity(Entity entity)

m_entities[entity.id] = entity;
m_systemNetwork.add(entity);
m_systemCollisionDetection.add(entity);
m_systemCollisionHandler.add(entity);
m_systemWormMovement.add(entity);
}

Expand All @@ -102,7 +110,10 @@ private void removeEntity(uint id)
{
m_entities.Remove(id);
m_systemNetwork.remove(id);
m_systemCollisionDetection.remove(id);
m_systemCollisionHandler.remove(id);
m_systemWormMovement.remove(id);

}

/// <summary>
Expand Down Expand Up @@ -134,6 +145,33 @@ private void handleJoin(int clientId, Shared.Messages.Message message)
// to the newly joined client
createNewWorm(clientId, name);
}

private void generateWalls()
{
// We want to create wall entities around the entire map. 5000x5000 is the size of the map
// We'll create a wall every 100 units
var wallSize = 100;
for (int i = 0; i < mapSize/100; i++)
{
// Top wall
Entity wall = Shared.Entities.Wall.create(new Vector2(i * wallSize, 0), wallSize);
addEntity(wall);
// MessageQueueServer.instance.broadcastMessage(new NewEntity(wall));
// Bottom wall
wall = Shared.Entities.Wall.create(new Vector2(i * wallSize, mapSize-wallSize), wallSize);
addEntity(wall);
// MessageQueueServer.instance.broadcastMessage(new NewEntity(wall));
// Left wall
wall = Shared.Entities.Wall.create(new Vector2(0, i * wallSize), wallSize);
addEntity(wall);
// MessageQueueServer.instance.broadcastMessage(new NewEntity(wall));
// Right wall
wall = Shared.Entities.Wall.create(new Vector2(mapSize-wallSize, i * wallSize), wallSize);
addEntity(wall);
// MessageQueueServer.instance.broadcastMessage(new NewEntity(wall));
}

}

private void createNewWorm(int clientId, string name)
{
Expand Down Expand Up @@ -201,7 +239,9 @@ private Vector2 getLeastDenseStartLocation()
// We want to start the player in the least dense area of the screen
// For now, we'll just start them randomly generated location
Random random = new Random();
return new Vector2(random.Next(0, 800), random.Next(0, 600));
var lowerBound = (int)(.1 * mapSize);
var upperBound = (int)(.9 * mapSize);
return new Vector2(random.Next(lowerBound, upperBound), random.Next(lowerBound, upperBound));
}
}
}
1 change: 0 additions & 1 deletion src/Server/MessageQueueServer.cs
Original file line number Diff line number Diff line change
Expand Up @@ -161,7 +161,6 @@ public void broadcastMessageWithLastId(Message message)
public void registerConnectHandler(ConnectHandler handler)
{
m_connectHandler = handler;

}

/// <summary>
Expand Down
Loading

0 comments on commit d072166

Please sign in to comment.