Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

updates to use collidable and adds collision message #74

Merged
merged 1 commit into from
Apr 11, 2024
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 1 addition & 1 deletion README.md
Original file line number Diff line number Diff line change
Expand Up @@ -21,10 +21,10 @@ A game of Snake built using C# in the MonoGame framework, themed around everyone
- [ ] Leaderboard to display top 5 players and client's score in corner of game.
- [ ] Add a player status in leaderboard to show whether the player is currently invincible.
- [ ] Port Particle System - Satchel
- [ ] Message receiver for the client about collisions that can be used to call the particle system and sound effects.

## Done

- [x] Max: Collision message and its wiring for the client to then render its own effects.
- [x] Max: 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.
- [x] Max: On collision, sandworm breaks apart and is available as food for other snakes
- [x] Max: Grow the worm on eating food.
Expand Down
40 changes: 39 additions & 1 deletion src/Client/GameModel.cs
Original file line number Diff line number Diff line change
Expand Up @@ -10,6 +10,7 @@
using Client.Components;
using Shared.Components;
using Shared.Entities;
using Shared.Messages;
using Shared.Systems;

namespace Client;
Expand All @@ -30,6 +31,7 @@ public class GameModel
private SpriteFont m_font;
private Texture2D m_sand;
private String m_playerName;
private PlayerData m_playerData;

public GameModel(StringBuilder playerName)
{
Expand All @@ -47,6 +49,7 @@ public void update(TimeSpan elapsedTime)
m_systemWormMovement.update(elapsedTime);
m_systemInterpolation.update(elapsedTime);
m_systemCamera.update(elapsedTime);
// m_systemScore.update(elapsedTime); // TODO
}

/// <summary>
Expand Down Expand Up @@ -80,6 +83,7 @@ public bool initialize(ContentManager contentManager, Controls controls, Graphic

m_systemNetwork.registerNewEntityHandler(handleNewEntity);
m_systemNetwork.registerRemoveEntityHandler(handleRemoveEntity);
m_systemNetwork.registerCollisionHandler(handleCollision);
m_controls = controls;

m_systemKeyboardInput = new Systems.KeyboardInput(new List<Tuple<Shared.Components.Input.Type, Keys>>
Expand Down Expand Up @@ -128,7 +132,7 @@ private Entity createEntity(Shared.Messages.NewEntity message)

if (message.hasCollision)
{
entity.add(new Collision());
entity.add(new Collidable());
}

if (message.hasWall)
Expand Down Expand Up @@ -235,5 +239,39 @@ private void handleRemoveEntity(Shared.Messages.RemoveEntity message)
{
removeEntity(message.id);
}

private void handleCollision(Shared.Messages.Collision message)
{
// We need to know if the collision occurred on the screen of the client
if (m_entities.ContainsKey(message.entity1Id) && m_entities.ContainsKey(message.entity2Id))
{

if (message.collisionType == Collision.CollisionType.HeadToSpice)
{
// TODO: Spice particle effect collision flag
}

if (message.collisionType == Collision.CollisionType.HeadToWall)
{
// TODO: Wall particle effect collision flag
}

// We hit another worm

// Grab the entities
var entity1 = m_entities[message.entity1Id];
var entity2 = m_entities[message.entity2Id];
// Check the position
var position = message.position;

// Check where our current client is and see if the collision is relevant
// TODO: Implement this

// If it is relevant, we either send a boolean flag to the particle system and collision handling or we call those here.

// TODO: Implement this

}
}
}

1 change: 1 addition & 0 deletions src/Client/MessageQueueClient.cs
Original file line number Diff line number Diff line change
Expand Up @@ -56,6 +56,7 @@ public bool initialize(string address, ushort port)
m_messageCommand[Shared.Messages.Type.NewEntity] = () => { return new NewEntity(); };
m_messageCommand[Shared.Messages.Type.UpdateEntity] = () => { return new UpdateEntity(); };
m_messageCommand[Shared.Messages.Type.RemoveEntity] = () => { return new RemoveEntity(); };
m_messageCommand[Shared.Messages.Type.Collision] = () => { return new Collision(); };

try
{
Expand Down
11 changes: 11 additions & 0 deletions src/Client/Systems/CollisionHandler.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,11 @@
using System;

namespace Client.Systems;

public class CollisionHandler : Shared.Systems.System
{
public override void update(TimeSpan elapsedTime)
{
throw new NotImplementedException();
}
}
13 changes: 13 additions & 0 deletions src/Client/Systems/Network.cs
Original file line number Diff line number Diff line change
Expand Up @@ -19,9 +19,12 @@ public class Network : Shared.Systems.System
public delegate void Handler(TimeSpan elapsedTime, Shared.Messages.Message message);
public delegate void RemoveEntityHandler(RemoveEntity message);
public delegate void NewEntityHandler(NewEntity message);
public delegate void CollisionHandler(Collision message);

private Dictionary<Shared.Messages.Type, Handler> m_commandMap = new Dictionary<Shared.Messages.Type, Handler>();
private RemoveEntityHandler m_removeEntityHandler;
private NewEntityHandler m_newEntityHandler;
private CollisionHandler m_collisionHandler;
private uint m_lastMessageId = 0;
private HashSet<uint> m_updatedEntities = new HashSet<uint>();

Expand Down Expand Up @@ -53,6 +56,11 @@ public Network(String playerName) :
m_removeEntityHandler((RemoveEntity)message);
});

registerHandler(Shared.Messages.Type.Collision, (TimeSpan elapsedTime, Message message) =>
{
m_collisionHandler((Collision)message);
});

}

// Have to implement this because it is abstract in the base class
Expand Down Expand Up @@ -147,6 +155,11 @@ public void registerRemoveEntityHandler(RemoveEntityHandler handler)
{
m_removeEntityHandler = handler;
}

public void registerCollisionHandler(CollisionHandler handler)
{
m_collisionHandler = handler;
}

/// <summary>
/// Handler for the ConnectAck message. This records the clientId
Expand Down
8 changes: 1 addition & 7 deletions src/Client/Systems/Renderer.cs
Original file line number Diff line number Diff line change
@@ -1,16 +1,13 @@
using Microsoft.Xna.Framework;
using Microsoft.Xna.Framework.Graphics;
using Microsoft.Xna.Framework.Content;

using Shared.Entities;
using Shared.Components;
using Shared.Components.Appearance;

using System;
using System.Collections.Generic;
using Client.Components;
using Client.Menu;
using System.Runtime.CompilerServices;
using Shared.Systems;

namespace Client.Systems;
Expand Down Expand Up @@ -106,10 +103,7 @@ private void renderEntity(TimeSpan elapsedTime, SpriteBatch spriteBatch, Entity
if (entity.contains<Invincible>())
{
var invincible = entity.get<Invincible>();
if (invincible.duration < 1000)
color = Color.Coral;
else
color = Colors.displayColor;
color = invincible.duration < 1000 ? Color.Coral : Colors.displayColor;
}

if (entity.contains<SpicePower>() && !entity.contains<Worm>())
Expand Down
35 changes: 22 additions & 13 deletions src/Server/Systems/CollisionDetection.cs
Original file line number Diff line number Diff line change
Expand Up @@ -18,9 +18,9 @@

public static int POWER_TO_GROW = 50;

public CollisionDetection() :

Check warning on line 21 in src/Server/Systems/CollisionDetection.cs

View workflow job for this annotation

GitHub Actions / buildProject

Non-nullable field 'm_removeEntity' must contain a non-null value when exiting constructor. Consider declaring the field as nullable.

Check warning on line 21 in src/Server/Systems/CollisionDetection.cs

View workflow job for this annotation

GitHub Actions / buildProject

Non-nullable field 'm_addEntity' must contain a non-null value when exiting constructor. Consider declaring the field as nullable.

Check warning on line 21 in src/Server/Systems/CollisionDetection.cs

View workflow job for this annotation

GitHub Actions / buildProject

Non-nullable field 'm_updateEntity' must contain a non-null value when exiting constructor. Consider declaring the field as nullable.
base(
typeof(Shared.Components.Collision), typeof(Shared.Components.Position), typeof(Shared.Components.Size)
typeof(Shared.Components.Collidable), typeof(Shared.Components.Position), typeof(Shared.Components.Size)
)
{
}
Expand Down Expand Up @@ -101,7 +101,7 @@
CircleLineIntersect(headPos, head.get<Size>().size.X / 2, bottomLeft, bottomRight) ||
CircleLineIntersect(headPos, head.get<Size>().size.X / 2, topRight, bottomRight))
{
handleWormHitWall(worm);
handleWormHitWall(worm, entity);
}
}
}
Expand Down Expand Up @@ -133,6 +133,9 @@

private void handleWormAteSpice(Entity head, Entity spice, TimeSpan elapsedTime)
{
// There was a collision let everyone know about it
MessageQueueServer.instance.broadcastMessage(new Collision(head.id, spice.id,
Collision.CollisionType.HeadToSpice, head.get<Position>()));
// Remove the spice
m_removeEntity(spice.id);
MessageQueueServer.instance.broadcastMessage(new RemoveEntity(spice.id));
Expand Down Expand Up @@ -182,36 +185,42 @@
{
return;
}

// Check if we hit head on head
if (otherHead.contains<Head>())
{
// There was a collision let everyone know about it
MessageQueueServer.instance.broadcastMessage(new Collision(worm[0].id, otherHead.id,
Collision.CollisionType.HeadToHead, worm[0].get<Position>()));
// We need to compare the sizes of the two worms to see who dies
List<Entity> otherWorm = WormMovement.getWormFromHead(otherHead, m_entities);
if (worm.Count > otherWorm.Count)
{
handleRemoveWormAndGenerateSpice(otherWorm);
}
else
{
handleRemoveWormAndGenerateSpice(worm);
{
handleRemoveWormAndGenerateSpice(worm);
}
}
else // We hit the side of the worm
{
// There was a collision let everyone know about it
MessageQueueServer.instance.broadcastMessage(new Collision(worm[0].id, otherHead.id,
Collision.CollisionType.HeadToBody, worm[0].get<Position>()));
// If the worm hit the body, then the worm dies
if (!worm[0].contains<Invincible>())
{
handleRemoveWormAndGenerateSpice(worm);
}
handleRemoveWormAndGenerateSpice(worm);
}
}

private void handleWormHitWall(List<Entity> worm)
private void handleWormHitWall(List<Entity> worm, Entity wall)
{
if (!worm[0].contains<Invincible>())
{
handleRemoveWormAndGenerateSpice(worm);
}
if (worm[0].contains<Invincible>()) return;

// There was a collision let everyone know about it
MessageQueueServer.instance.broadcastMessage(new Collision(worm[0].id, wall.id,
Collision.CollisionType.HeadToWall, wall.get<Position>()));
handleRemoveWormAndGenerateSpice(worm);
}

private void handleRemoveWormAndGenerateSpice(List<Entity> worm)
Expand Down
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
namespace Shared.Components;

public class Collision: Component
public class Collidable: Component
{

}
2 changes: 1 addition & 1 deletion src/Shared/Entities/DeadWormSpice.cs
Original file line number Diff line number Diff line change
Expand Up @@ -14,7 +14,7 @@ public static Entity create(Vector2 position)
entity.add(new Appearance("Textures/deadWormSpice"));
entity.add(new Position(position));
entity.add(new Size(new Vector2(size, size)));
entity.add(new Collision());
entity.add(new Collidable());
entity.add(new SpicePower(10));
return entity;
}
Expand Down
19 changes: 0 additions & 19 deletions src/Shared/Entities/Particle.cs

This file was deleted.

2 changes: 1 addition & 1 deletion src/Shared/Entities/Spice.cs
Original file line number Diff line number Diff line change
Expand Up @@ -15,7 +15,7 @@ public static Entity create(Vector2 position)
entity.add(new Appearance("Textures/spice"));
entity.add(new Position(position));
entity.add(new Size(new Vector2(size, size)));
entity.add(new Collision());
entity.add(new Collidable());
entity.add(new SpicePower(power));
return entity;
}
Expand Down
Loading
Loading