WIP: Add multiplayer Snake game
N-player (2-8) real-time Snake game alongside Connect 4. Lobby has tabs to switch between games. Players join via invite link with 10-second countdown. Game loop runs at tick-based intervals with NATS pub/sub for state sync. Keyboard input not yet working (Datastar keydown binding issue still under investigation).
This commit is contained in:
74
ui/snakelobby.go
Normal file
74
ui/snakelobby.go
Normal file
@@ -0,0 +1,74 @@
|
||||
package ui
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
|
||||
"github.com/ryanhamamura/c4/snake"
|
||||
"github.com/ryanhamamura/via/h"
|
||||
)
|
||||
|
||||
func SnakeLobbyTab(nicknameBind h.H, presetClicks []h.H, activeGames []*snake.SnakeGame) h.H {
|
||||
var presetButtons []h.H
|
||||
for i, preset := range snake.GridPresets {
|
||||
var click h.H
|
||||
if i < len(presetClicks) {
|
||||
click = presetClicks[i]
|
||||
}
|
||||
presetButtons = append(presetButtons,
|
||||
h.Button(
|
||||
h.Class("btn btn-primary"),
|
||||
h.Type("button"),
|
||||
h.Text(fmt.Sprintf("%s (%d×%d)", preset.Name, preset.Width, preset.Height)),
|
||||
click,
|
||||
),
|
||||
)
|
||||
}
|
||||
|
||||
createSection := h.Div(h.Class("mb-6"),
|
||||
h.H3(h.Class("text-lg font-bold mb-2"), h.Text("Create Game")),
|
||||
h.Div(h.Class("mb-4"),
|
||||
h.FieldSet(h.Class("fieldset"),
|
||||
h.Label(h.Class("label"), h.Text("Your Nickname"), h.Attr("for", "snake-nickname")),
|
||||
h.Input(
|
||||
h.Class("input input-bordered w-full"),
|
||||
h.ID("snake-nickname"),
|
||||
h.Type("text"),
|
||||
h.Placeholder("Enter your nickname"),
|
||||
nicknameBind,
|
||||
h.Attr("required"),
|
||||
),
|
||||
),
|
||||
),
|
||||
h.Div(append([]h.H{h.Class("flex gap-2 justify-center")}, presetButtons...)...),
|
||||
)
|
||||
|
||||
var gameListEl h.H
|
||||
if len(activeGames) > 0 {
|
||||
var items []h.H
|
||||
for _, g := range activeGames {
|
||||
playerCount := g.PlayerCount()
|
||||
sizeLabel := fmt.Sprintf("%d×%d", g.State.Width, g.State.Height)
|
||||
statusLabel := "Waiting"
|
||||
if g.Status == snake.StatusCountdown {
|
||||
statusLabel = "Starting soon"
|
||||
}
|
||||
items = append(items, h.A(
|
||||
h.Href("/snake/"+g.ID),
|
||||
h.Class("flex justify-between items-center p-3 bg-base-200 rounded-lg hover:bg-base-300 no-underline text-base-content"),
|
||||
h.Span(h.Text(fmt.Sprintf("%s — %d/8 players", sizeLabel, playerCount))),
|
||||
h.Span(h.Class("text-sm opacity-60"), h.Text(statusLabel)),
|
||||
))
|
||||
}
|
||||
listAttrs := []h.H{h.Class("flex flex-col gap-2")}
|
||||
listAttrs = append(listAttrs, items...)
|
||||
gameListEl = h.Div(h.Class("mt-6"),
|
||||
h.H3(h.Class("text-lg font-bold mb-2 text-center"), h.Text("Join a Game")),
|
||||
h.Div(listAttrs...),
|
||||
)
|
||||
}
|
||||
|
||||
return h.Div(
|
||||
createSection,
|
||||
gameListEl,
|
||||
)
|
||||
}
|
||||
Reference in New Issue
Block a user