Skip to content

Commit

Permalink
Adds snake rotation
Browse files Browse the repository at this point in the history
  • Loading branch information
MaxEdwards20 committed Apr 2, 2024
1 parent 49fa678 commit 1230093
Show file tree
Hide file tree
Showing 4 changed files with 104 additions and 30 deletions.
27 changes: 27 additions & 0 deletions src/Client/GameModel.cs
Original file line number Diff line number Diff line change
Expand Up @@ -105,6 +105,33 @@ private Entity createEntity(Shared.Messages.NewEntity message)
{
entity.add(new Shared.Components.Input(message.inputs));
}

// Worm parts

if (message.hasHead)
{
entity.add(new Head());
}

if (message.hasTail)
{
entity.add(new Tail());
}

if (message.hasParent)
{
entity.add(new ParentId(message.parentId));
}

if (message.hasChild)
{
entity.add(new ChildId(message.childId));
}

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

return entity;
}
Expand Down
1 change: 1 addition & 0 deletions src/Client/Systems/Renderer.cs
Original file line number Diff line number Diff line change
Expand Up @@ -41,6 +41,7 @@ public void render(TimeSpan elapsedTime, SpriteBatch spriteBatch)
matrix *= Matrix.CreateScale(scaleX, scaleY, 1);

spriteBatch.Begin(transformMatrix: matrix);
// TODO: Adjust this to render all of the tails first, then body segments, then heads
foreach (Entity entity in m_entities.Values)
renderEntity(elapsedTime, spriteBatch, entity);
spriteBatch.End();
Expand Down
17 changes: 10 additions & 7 deletions src/Server/GameModel.cs
Original file line number Diff line number Diff line change
Expand Up @@ -139,20 +139,23 @@ private void createNewWorm(int clientId)

// Create the head
Entity player = WormHead.create(startLocation, 100, moveRate, rotationRate);
addEntity(player);
m_clientToEntityId[clientId] = player.id;

// Create a body segment
Entity segment = WormSegment.create( startLocation + Vector2.One * 50, bodySize, moveRate, rotationRate, player.id);
addEntity(segment);
Entity segment = WormSegment.create( new Vector2(startLocation.X + 75, startLocation.Y - 20) , bodySize, moveRate, rotationRate, player.id);
player.add(new ChildId(segment.id));
m_clientToEntityId[clientId] = segment.id;

// Create a tail segment
Entity tail = WormTail.create(startLocation + Vector2.One * 100, bodySize, moveRate, rotationRate, segment.id);
addEntity(tail);
Entity tail = WormTail.create(new Vector2(startLocation.X + 130, startLocation.Y), bodySize, moveRate, rotationRate, segment.id);
segment.add(new ChildId(tail.id));

addEntity(player);
addEntity(segment);
addEntity(tail);

m_clientToEntityId[clientId] = player.id;
m_clientToEntityId[clientId] = segment.id;
m_clientToEntityId[clientId] = tail.id;


// Step 3: Send the new player entity to the newly joined client
MessageQueueServer.instance.sendMessage(clientId, new NewEntity(player));
Expand Down
89 changes: 66 additions & 23 deletions src/Shared/Entities/Utility.cs
Original file line number Diff line number Diff line change
Expand Up @@ -10,40 +10,27 @@ public class Utility
// Everything that hits these endpoints SHOULD be a WormHead (start of a LinkedList of worm parts)
public static void thrust(Entity entity, TimeSpan elapsedTime, Dictionary<uint, Entity> entities)
{
entity = getHead(entity, entities);
var position = entity.get<Position>();
var movement = entity.get<Movement>();

var vectorX = Math.Cos(position.orientation);
var vectorY = Math.Sin(position.orientation);

position.position = new Vector2(
(float)(position.position.X - vectorX * movement.moveRate * elapsedTime.Milliseconds),
(float)(position.position.Y - vectorY * movement.moveRate * elapsedTime.Milliseconds));
var head = getHead(entity, entities);
var snake = getSnakeFromHead(head, entities);
applyThrust(snake, elapsedTime);
}

public static void rotateLeft(Entity entity, TimeSpan elapsedTime, Dictionary<uint, Entity> entities)
{
entity = getHead(entity, entities);
var position = entity.get<Position>();
var movement = entity.get<Movement>();

position.orientation = position.orientation - movement.rotateRate * elapsedTime.Milliseconds;
var head = getHead(entity, entities);
applyLeftRotation(head, elapsedTime);
}

public static void rotateRight(Entity entity, TimeSpan elapsedTime, Dictionary<uint, Entity> entities)
{
entity = getHead(entity, entities);
var position = entity.get<Position>();
var movement = entity.get<Movement>();

position.orientation = position.orientation + movement.rotateRate * elapsedTime.Milliseconds;
var head = getHead(entity, entities);
applyRightRotation(head, elapsedTime);
}

private static Entity getHead(Entity entity, Dictionary<uint, Entity> entities)
{
var current = entity;
while (current.contains<ParentId>())
while (current.contains<ParentId>() && entities.ContainsKey(current.get<ParentId>().id))
{
current = entities[current.get<ParentId>().id];
}
Expand All @@ -57,7 +44,7 @@ private static List<Entity> getSnakeFromHead(Entity head, Dictionary<uint, Entit
while (current != null)
{
snakeEntities.Add(current);
if (current.contains<ChildId>())
if (current.contains<ChildId>() && entities.ContainsKey(current.get<ChildId>().id))
{
current = entities[current.get<ChildId>().id];
}
Expand All @@ -76,7 +63,7 @@ private static List<Entity> getSnakeFromTail(Entity tail, Dictionary<uint, Entit
while (current != null)
{
snakeEntities.Add(current);
if (current.contains<ParentId>())
if (current.contains<ParentId>() && entities.ContainsKey(current.get<ParentId>().id))
{
current = entities[current.get<ParentId>().id];
}
Expand All @@ -88,4 +75,60 @@ private static List<Entity> getSnakeFromTail(Entity tail, Dictionary<uint, Entit
return snakeEntities;
}

private static void applyThrust(List<Entity> snake, TimeSpan elapsedTime)
{
if (snake == null || snake.Count == 0)
{
return; // Early exit if snake is empty
}

// Calculate the movement vector for the head
var head = snake[0];
var headPosition = head.get<Position>();
var movement = head.get<Movement>();
var vectorX = Math.Cos(MathHelper.ToRadians(headPosition.orientation));
var vectorY = Math.Sin(MathHelper.ToRadians(headPosition.orientation));
var movementVector = new Vector2(
(float)(vectorX * movement.moveRate * elapsedTime.TotalSeconds),
(float)(vectorY * movement.moveRate * elapsedTime.TotalSeconds));

// Store the previous position of the head to calculate the offset for the next segment
Vector2 previousPosition = headPosition.position;
float previousOrientation = headPosition.orientation;
// Update the head position
headPosition.position += movementVector;

// Update each body segment's position based on the offset from its predecessor
for (int i = 1; i < snake.Count; i++)
{
var segment = snake[i];
var segmentPosition = segment.get<Position>();

// Calculate the offset for the current segment
Vector2 currentPosition = segmentPosition.position;
// Apply the offset from the previous segment to this one
segmentPosition.position = previousPosition + (currentPosition - previousPosition);
segmentPosition.orientation = previousOrientation;

// Update previousPosition for the next segment in the list
previousPosition = currentPosition;
previousOrientation = segmentPosition.orientation;
}
}


// We don't need to update the entire snake with these because it will be updated in the next frame when thrust is applied
private static void applyLeftRotation(Entity head, TimeSpan elapsedTime)
{
var position = head.get<Position>();
var movement = head.get<Movement>();
position.orientation -= movement.rotateRate * elapsedTime.Milliseconds;
}

private static void applyRightRotation(Entity head, TimeSpan elapsedTime)
{
var position = head.get<Position>();
var movement = head.get<Movement>();
position.orientation += movement.rotateRate * elapsedTime.Milliseconds;
}
}

0 comments on commit 1230093

Please sign in to comment.