昨天用 tailwind 画好首页
现在要做开始游戏前的等待对手页面
在这之前,我觉得差不多可以把 game 搬到 phoenix 里面了
就..把他移动到 lib/card/game.ex
但我们还是要调整一下 module 名称
从 Game
变成 Card.Game
,同时里面有一些用 %Game{}
的地方,
也要改,不过既然是在里面用的 我们可以写 %__MODULE__{}
就好
接着我们需要另一个 struct 来储存房间状态
这个也是 lib/card/room.ex
defmodule Card.Room do
defstruct id: nil, game: nil, game_pid: nil, host_ready: false, guest_ready: false
end
这个 struct 就可以替换掉我们昨天暂时写的 "房间状态"
在昨天的 lib/card_web/live/page_live/index.ex 最後两个方法
def handle_event("start_game", _params, socket) do
room_id = random_room_id()
:ets.insert_new(:rooms, {room_id, %Card.Room{id: room_id}})
{:noreply, push_redirect(socket, to: "/#{room_id}")}
end
# 这个跟昨天比少了 "room_" 我发现那个好像有点没意义
defp random_room_id(), do: String.trim(to_string(:rand.uniform), "0.")
打点好之後我们就可以来 router 帮路径补上
scope "/", CardWeb do
pipe_through :browser
live "/", PageLive.Index, :index
live "/:id/host", GameLive.Invite, :host
live "/:id/guest", GameLive.Invite, :guest
end
这边会分成两个,host 结尾的是我们要从 page index 导出去的连结
guest 是给我们复制贴给对手用的
写好之後在终端机打 mix phx.routes
他就会回传我们现在设定好的连结,跟 router helper 名称
page_index_path GET / Phoenix.LiveView.Plug :index
game_invite_path GET /:id/host Phoenix.LiveView.Plug :host
game_invite_path GET /:id/guest Phoenix.LiveView.Plug :guest
下略...
我们在 page index 按下开始游戏按钮後,就可以使用 Routes.game_invite_path(socket, :host, room_id)
这样:
def handle_event("start_game", _params, socket) do
room_id = random_room_id()
:ets.insert_new(:rooms, {room_id, %Card.Room{id: room_id}})
{:noreply, push_redirect(socket, to: Routes.game_invite_path(socket, :host, room_id))}
end
有了连结接着就是做出等待邀请的页面了
lib/card_web/live/game_live/invite.ex
一不注意就一次打完了... 只好加说明在里面
defmodule CardWeb.GameLive.Invite do
use CardWeb, :live_view
def mount(%{"id" => id} = params, session, socket) do
# 这边是拿网址里面的 id 去 ETS 的 rooms 表格找找看有没有纪录,没有的话就转到首页
# 有的话就在 socket 的 assigns 里面加入 room, player, invite_path(要邀请 guest 的连结)
case :ets.lookup(:rooms, id) do
[{_, room}] ->
{:ok, assign(socket, %{room: room, player: socket.assigns.live_action, invite_path: Routes.game_invite_url(socket, :guest, id)})}
_ ->
{:ok, push_redirect(socket, to: "/")}
end
end
def render(assigns) do
# 因为刚刚已经有把要用的东西加进 assigns 里面,这边就可以直接用 @ 取值
~H"""
<div class="flex flex-col items-center h-screen">
<header class="text-blue-500 m-4">
<a href="/" class="text-5xl font-serif">
? CardyTotala
</a>
</header>
<div class="flex-grow flex flex-col items-center justify-center">
<%=# 如果玩家是 host 而且 guest 还没准备好的话 显示邀请连结 %>
<%= if @player == :host && [email protected]_ready do %>
<.invite path={@invite_path}/>
<% end %>
</div>
</div>
"""
end
def invite(assigns) do
~H"""
<div class="flex flex-col p-4 bg-grey-50 shadow-lg text-center mt-8">
<div class="bg-blue-300 w-40 h-8 rounded-xl transform skew-x-12 rotate-6 translate-y-6 translate-x-40"></div>
<div class="transform">
<label for="invite_url" class="text-2xl font-serif">Guest Link</label><br>
<input id="invite_url" class="w-96 text-center text-gray-500" type="text" value={@path} readonly>
</div>
<p class="text-lg text-gray-600">To begin the game, send this link to your component.</p>
</div>
"""
end
end
刚刚上面有 <.invite /> 这种东西,这个是 heex 专用的 component 写法,不是 html
是 phoenix 1.6 刚加进去的,我们看到另一个方法叫 invite(assigns) 就可以猜到
他就是去执行并 render 里面的东西取代掉 <.invite />
另外在 heex 里面不能在html tag 上使用 #{}
以前是这样
# text_color = "text-red-600"
~L"""
<p class="#{text_color}">
"""
但 heex 不行这样用
现在要改用
# text_color = "text-red-600"
~H"""
<p class={text_color}>
"""
所以现在邀请页面长这样
<<: D24 - 用 Swift 和公开资讯,打造投资理财的 Apps { 台股成交量实作.4 }
动机 这篇内容讲的是我在今年暑假参加 AIS3 暑期营队软件安全组所做的专题,队友分别为郑永泰、许智...
上篇大概介绍一下我们所运用的js与方法, 今天我们要先来写python api的部分。 (1)首先新...
文章同步更新於个人官网 https://kevinyay945.com/smart-home-tut...
在现在这种讲求快速开发的开发模式,我们通常不太会自己将所有功能都自己硬刻出来,而是会去使用第三方的套...
小勘误: 前几天提到我们会把六大类都至少做过一题,但是 picoCTF 的 Misc 类 -- U...