Skip to content

Commit

Permalink
Handle delta states in game_client (#907)
Browse files Browse the repository at this point in the history
* Handle the new vertices as a list of positions

* Handle deltas for crates, bushes, and obstacles
  • Loading branch information
AminArria authored Sep 10, 2024
1 parent dcab0f6 commit 4f3436b
Showing 1 changed file with 81 additions and 5 deletions.
86 changes: 81 additions & 5 deletions apps/game_client/lib/game_client_web/live/pages/board/show.ex
Original file line number Diff line number Diff line change
Expand Up @@ -34,7 +34,8 @@ defmodule GameClientWeb.BoardLive.Show do
game_socket_handler_pid: game_socket_handler_pid,
backend_board_size: backend_board_size,
back_size_to_front_ratio: back_size_to_front_ratio,
map_radius: map_radius
map_radius: map_radius,
game_state: nil
)}
end

Expand Down Expand Up @@ -87,7 +88,9 @@ defmodule GameClientWeb.BoardLive.Show do
{:noreply, push_event(socket, "joinedGame", %{})}
end

defp handle_game_event({:update, game_state}, socket) do
defp handle_game_event({:update, game_state_delta}, socket) do
game_state = process_game_state_delta(game_state_delta, socket.assigns.game_state)

entities =
Enum.concat([
game_state.players,
Expand All @@ -101,6 +104,7 @@ defmodule GameClientWeb.BoardLive.Show do
])
|> Enum.map(fn entity -> transform_entity_entry(entity, socket) end)

socket = assign(socket, game_state: game_state)
{:noreply, push_event(socket, "updateEntities", %{entities: entities, player_id: socket.assigns.game_player_id})}
end

Expand All @@ -127,7 +131,7 @@ defmodule GameClientWeb.BoardLive.Show do
y: entity.position.y / back_size_to_front_ratio + backend_board_size / 10,
radius: entity.radius / back_size_to_front_ratio,
coords:
entity.vertices
entity.vertices.positions
|> Enum.map(fn vertex ->
[vertex.x / back_size_to_front_ratio, vertex.y / back_size_to_front_ratio]
end),
Expand All @@ -151,7 +155,7 @@ defmodule GameClientWeb.BoardLive.Show do
back_x: entity.position.x,
back_y: entity.position.y,
radius: entity.radius / back_size_to_front_ratio,
coords: entity.vertices |> Enum.map(fn vertex -> [vertex.x / 5, vertex.y / 5] end),
coords: Enum.map(entity.vertices.positions, fn vertex -> [vertex.x / 5, vertex.y / 5] end),
is_colliding: entity.collides_with |> Enum.any?(),
visible_players: aditional_info.visible_players,
effects: Enum.map(aditional_info.effects, fn effect -> effect.name end),
Expand All @@ -171,11 +175,83 @@ defmodule GameClientWeb.BoardLive.Show do
y: entity.position.y / back_size_to_front_ratio + backend_board_size / 10,
radius: entity.radius / back_size_to_front_ratio,
coords:
entity.vertices
entity.vertices.positions
|> Enum.map(fn vertex ->
[vertex.x / back_size_to_front_ratio, vertex.y / back_size_to_front_ratio]
end),
is_colliding: entity.collides_with |> Enum.any?()
}
end

defp process_game_state_delta(game_state_delta, nil) do
game_state_delta
end

defp process_game_state_delta(game_state_delta, game_state) do
## This can be done using `game_state_delta` as the base instead of `game_state` cause there are only a few things we are actually
## sending as deltas (obstacles, bushes, crates), everything else is still fully sent. So its simpler to use it as the base
%{
game_state_delta
| obstacles: process_fixed_entities_delta(game_state_delta.obstacles, game_state.obstacles),
bushes: process_fixed_entities_delta(game_state_delta.bushes, game_state.bushes),
crates: process_fixed_entities_delta(game_state_delta.crates, game_state.crates)
}
end

## Process delta for entities that are never created/removed, hence "fixed" (as in fixed position)
defp process_fixed_entities_delta(entities_delta, entities) do
Enum.reduce(entities_delta, entities, fn {entity_id, entity_delta}, entities_acc ->
old_entity = Map.get(entities_acc, entity_id)
Map.put(entities_acc, entity_id, process_entity_delta(entity_delta, old_entity))
end)
end

defp process_entity_delta(entity_delta, nil) do
entity_delta
end

defp process_entity_delta(entity_delta, entity) do
%{
entity
| collides_with: entity_delta.collides_with,
radius: new_value_or_old(entity_delta.radius, entity.radius),
speed: new_value_or_old(entity_delta.speed, entity.speed),
is_moving: new_value_or_old(entity_delta.is_moving, entity.is_moving),
position: process_delta_point(entity_delta.position, entity.position),
direction: process_delta_point(entity_delta.direction, entity.direction),
aditional_info: process_entity_additional_delta(entity_delta.aditional_info, entity.aditional_info)
}
end

defp process_entity_additional_delta(nil, nil) do
nil
end

defp process_entity_additional_delta({:obstacle, obstacle_delta}, {:obstacle, obstacle}) do
{:obstacle,
%{
obstacle_delta
| color: new_value_or_old(obstacle_delta.color, obstacle.color),
collisionable: new_value_or_old(obstacle_delta.collisionable, obstacle.collisionable),
status: new_value_or_old(obstacle_delta.status, obstacle.status),
type: new_value_or_old(obstacle_delta.type, obstacle.type)
}}
end

defp process_entity_additional_delta({:crate, crate_delta}, {:crate, crate}) do
{:crate,
%{
crate_delta
| health: new_value_or_old(crate_delta.health, crate.health),
amount_of_power_ups: new_value_or_old(crate_delta.amount_of_power_ups, crate.amount_of_power_ups),
status: new_value_or_old(crate_delta.status, crate.status)
}}
end

defp process_delta_point(nil, point), do: point
defp process_delta_point(point_delta, point), do: Map.merge(point, point_delta)

defp new_value_or_old(nil, old), do: old
defp new_value_or_old(:CRATE_STATUS_UNDEFINED, old), do: old
defp new_value_or_old(new, _old), do: new
end

0 comments on commit 4f3436b

Please sign in to comment.