Skip to content

Commit

Permalink
Checkpoint.
Browse files Browse the repository at this point in the history
  • Loading branch information
alexpearce committed Oct 27, 2023
1 parent cc16b29 commit 6ebd2ce
Show file tree
Hide file tree
Showing 12 changed files with 172 additions and 59 deletions.
94 changes: 93 additions & 1 deletion assets/css/app.css
Original file line number Diff line number Diff line change
Expand Up @@ -2,4 +2,96 @@
@import "tailwindcss/components";
@import "tailwindcss/utilities";

/* This file is for your main application CSS */
:root {
--background-color: #fce7f3;
--text-color: #ec4899;
}

* {
box-sizing: border-box;
}

html, body {
margin: 0;
padding: 0;
font-family: -apple-system, BlinkMacSystemFont, "Segoe UI", Roboto, Helvetica, Arial, sans-serif, "Apple Color Emoji", "Segoe UI Emoji", "Segoe UI Symbol";
font-size: 16px;
}

html {
display: flex;
flex-direction: column;
align-items: center;
justify-content: center;
background-color: var(--background-color);
}

body {
width: 100%;
padding: 24px;
}

@media (min-width: 560px) {
body {
width: 560px;
}

}

h1 {
margin: 0;
padding: 1rem 0;
font-size: 2.0rem;
font-weight: 800;
}

h1 {
color: var(--text-color);
}

.game {
padding: 8px;
background-color: #fbcfe8;
border-radius: 8px;
border: 4px solid rgba(255, 255, 255,0.25);
}

.stats {
display: flex;
margin: 0 0 1rem 0;
justify-content: space-between;
}

.message {
display: flex;
margin: 0 0 1rem 0;
justify-content: center;
font-weight: 800;
}

.board {
display: grid;
gap: 10px;
font-size: 1.5rem;
}

.cell {
width: 100%;
display: flex;
align-items: center;
justify-content: center;
--cell-lightness: calc(2 * log(var(--cell-value) + 1));
background-color: hsl(0, 100%, calc(95% - var(--cell-lightness) * 1%));
background-color: hsl(0, 100%, 0.95);
border: 3px solid rgba(255, 255, 255,0.25);
border-radius: 5px;
color: rgba(0, 0, 0, 0.75);
}

.cell::before {
content: "";
display: inline-block;
width: 1px;
height: 0;
padding-bottom: 100%;
}
2 changes: 1 addition & 1 deletion lib/twenty_fourty_eight/game/manager.ex
Original file line number Diff line number Diff line change
Expand Up @@ -6,7 +6,7 @@ defmodule TwentyFourtyEight.Game.Manager do
@registry TwentyFourtyEight.Game.Registry
@supervisor TwentyFourtyEight.Game.Supervisor

def new_game(name) when is_binary(name) do
def get_game(name) when is_binary(name) do
case Registry.lookup(@registry, name) do
[{pid, _value}] -> {:ok, pid}
[] -> DynamicSupervisor.start_child(@supervisor, {__MODULE__, name})
Expand Down
9 changes: 2 additions & 7 deletions lib/twenty_fourty_eight_web/components/layouts/app.html.heex
Original file line number Diff line number Diff line change
@@ -1,7 +1,2 @@
<main class="px-4 py-20 sm:px-6 lg:px-8">
<div class="mx-auto max-w-2xl">
<h1 class="text-4xl text-center font-bold py-6 tracking-tight">Twenty Fourty Eight</h1>
<.flash_group flash={@flash} />
<%= @inner_content %>
</div>
</main>
<.flash_group flash={@flash} />
<%= @inner_content %>
6 changes: 4 additions & 2 deletions lib/twenty_fourty_eight_web/components/layouts/root.html.heex
Original file line number Diff line number Diff line change
Expand Up @@ -4,14 +4,16 @@
<meta charset="utf-8" />
<meta name="viewport" content="width=device-width, initial-scale=1" />
<meta name="csrf-token" content={get_csrf_token()} />
<.live_title suffix=" · Phoenix Framework">
<.live_title>
<%= assigns[:page_title] || "TwentyFourtyEight" %>
</.live_title>
<link phx-track-static rel="stylesheet" href={~p"/assets/app.css"} />
<script defer phx-track-static type="text/javascript" src={~p"/assets/app.js"}>
</script>
</head>
<body class="bg-white antialiased">
<body>
<h1>Twenty Fourty Eight.</h1>
<.flash_group flash={@flash} />
<%= @inner_content %>
</body>
</html>
11 changes: 11 additions & 0 deletions lib/twenty_fourty_eight_web/controllers/game_controller.ex
Original file line number Diff line number Diff line change
@@ -0,0 +1,11 @@
defmodule TwentyFourtyEightWeb.GameController do
use TwentyFourtyEightWeb, :controller

def new(conn, _params) do
render(conn, :new)
end

def create(conn, _params) do
redirect(conn, to: ~p"/#{id}")
end
end
5 changes: 5 additions & 0 deletions lib/twenty_fourty_eight_web/controllers/game_html.ex
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
defmodule TwentyFourtyEightWeb.GameHTML do
use TwentyFourtyEightWeb, :html

embed_templates "game_html/*"
end
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
Yo!
9 changes: 0 additions & 9 deletions lib/twenty_fourty_eight_web/controllers/page_controller.ex

This file was deleted.

5 changes: 0 additions & 5 deletions lib/twenty_fourty_eight_web/controllers/page_html.ex

This file was deleted.

This file was deleted.

85 changes: 53 additions & 32 deletions lib/twenty_fourty_eight_web/live/game_live.ex
Original file line number Diff line number Diff line change
Expand Up @@ -3,38 +3,32 @@ defmodule TwentyFourtyEightWeb.GameLive do

alias TwentyFourtyEight.Game.Manager, as: GameManager

# Support arrows keys as well as hjkl (Vim) and wasd (gaming).
@up_keys ["ArrowUp", "w", "k"]
@down_keys ["ArrowDown", "s", "j"]
@left_keys ["ArrowLeft", "a", "h"]
@right_keys ["ArrowRight", "d", "l"]
@known_keys @up_keys ++ @down_keys ++ @left_keys ++ @right_keys

def render(assigns) do
~H"""
<div class="container bg-slate-100">
Name: <%= @name %>
Turn number: <%= @turns %>
Score: <%= @score %>
<!--
Possible grid sizes:
grid-cols-1 grid-cols-2 grid-cols-3 grid-cols-4 grid-cols-5 grid-cols-6
grid-rows-1 grid-rows-2 grid-rows-3 grid-rows-4 grid-rows-5 grid-rows-6
-->
<div class={"grid grid-cols-#{@num_cols} gap-4 h-96 text-3xl p-6"} phx-window-keyup="move">
<%= for row <- 1..@num_rows do %>
<%= for col <- 1..@num_cols do %>
<%= if is_nil(@board[{row, col}]) do %>
<div class="flex justify-center items-center bg-slate-200 border-2 border-slate-300 rounded-lg">&nbsp;</div>
<% else %>
<div class="flex justify-center items-center bg-slate-300 border-2 border-slate-400 rounded-lg"><%= @board[{row, col}] %></div>
<% end %>
<% end %>
<% end %>
<div class="game">
<div class="stats">
<div><b>Name</b> <code><%= @name %></code></div>
<div><b>Score</b> <%= @score %></div>
<div><b>Turns</b> <%= @turns %></div>
</div>
<div class="message"><%= status_message(@state) %></div>
<.board num_rows={@num_rows} num_cols={@num_cols} cell_values={@board} />
</div>
"""
end

def mount(%{"name" => name} = _params, _session, socket) do
# TODO this is called twice, once at GET and once at WS connection.
# no need to create two games! just need to make sure assigns are
# filled in with placeholders
{:ok, pid} = GameManager.new_game(name)
Process.link(pid)
{:ok, pid} = GameManager.get_game(name)
# This will kill the game when the LV dies, e.g. after the initial GET
# request (before the socket has connected).
# Process.link(pid)

socket = socket
|> assign_game(name)
Expand All @@ -46,19 +40,20 @@ defmodule TwentyFourtyEightWeb.GameLive do
{:ok, push_navigate(socket, to: "/#{name}")}
end

def handle_event("move", %{"key" => key}, %{assigns: %{name: name}} = socket) when key in ~w(h j k l) do
@doc """
Handle known key events whilst the game is running.
"""
def handle_event("move", %{"key" => key}, %{assigns: %{name: name, state: :running}} = socket) when key in @known_keys do
:ok = GameManager.tick(name, key_to_move(key))
{:noreply, assign_game_state(socket, name)}
end

def handle_event("move", params, socket) do
{:noreply, socket}
end
def handle_event("move", params, socket), do: {:noreply, socket}

defp key_to_move("h"), do: :left
defp key_to_move("j"), do: :down
defp key_to_move("k"), do: :up
defp key_to_move("l"), do: :right
defp key_to_move(up) when up in @up_keys, do: :up
defp key_to_move(down) when down in @down_keys, do: :down
defp key_to_move(left) when left in @left_keys, do: :left
defp key_to_move(right) when right in @right_keys, do: :right

defp generate_name do
?a..?z
Expand All @@ -79,4 +74,30 @@ defmodule TwentyFourtyEightWeb.GameLive do
|> assign(num_rows: num_rows, num_cols: num_cols, board: board)
|> assign(game_state)
end

defp status_message(:running), do: ""
defp status_message(:won), do: "You won!"
defp status_message(:exhausted), do: "Game over!"

defp board(assigns) do
~H"""
<div class="board" style={"grid-template-columns: repeat(#{@num_cols}, 1fr);"} phx-window-keyup="move">
<%= for row <- 1..@num_rows do %>
<%= for col <- 1..@num_cols do %>
<.cell value={@cell_values[{row, col}]} />
<% end %>
<% end %>
</div>
"""
end

defp cell(assigns) do
~H"""
<%= if is_nil(@value) do %>
<div class="cell" style="--cell-value: 0;">&nbsp;</div>
<% else %>
<div class="cell" style={"--cell-value: #{@value};"}><%= @value %></div>
<% end %>
"""
end
end
3 changes: 2 additions & 1 deletion lib/twenty_fourty_eight_web/router.ex
Original file line number Diff line number Diff line change
Expand Up @@ -17,7 +17,8 @@ defmodule TwentyFourtyEightWeb.Router do
scope "/", TwentyFourtyEightWeb do
pipe_through :browser

live "/", GameLive
get "/", GameController, :new
post "/", GameController, :create
live "/:name", GameLive
end

Expand Down

0 comments on commit 6ebd2ce

Please sign in to comment.