Rename module path github.com/ryanhamamura/c4 to github.com/ryanhamamura/games across go.mod, all source files, and golangci config.
138 lines
3.8 KiB
Plaintext
138 lines
3.8 KiB
Plaintext
package components
|
|
|
|
import (
|
|
"fmt"
|
|
"math"
|
|
"time"
|
|
|
|
"github.com/ryanhamamura/games/config"
|
|
"github.com/ryanhamamura/games/snake"
|
|
"github.com/starfederation/datastar-go/datastar"
|
|
)
|
|
|
|
templ StatusBanner(sg *snake.SnakeGame, mySlot int, gameID string) {
|
|
<div id="snake-status">
|
|
switch sg.Status {
|
|
case snake.StatusWaitingForPlayers:
|
|
if sg.Mode == snake.ModeSinglePlayer {
|
|
<div class="alert bg-base-200 text-xl font-bold">Ready?</div>
|
|
} else {
|
|
<div class="alert bg-base-200 text-xl font-bold">Waiting for players...</div>
|
|
}
|
|
case snake.StatusCountdown:
|
|
{{ remaining := time.Until(sg.CountdownEnd) }}
|
|
{{ secs := int(math.Ceil(remaining.Seconds())) }}
|
|
if secs < 0 {
|
|
{{ secs = 0 }}
|
|
}
|
|
<div class="alert alert-info text-xl font-bold">
|
|
{ fmt.Sprintf("Starting in %d...", secs) }
|
|
</div>
|
|
case snake.StatusInProgress:
|
|
if sg.State != nil && mySlot >= 0 && mySlot < len(sg.State.Snakes) && sg.State.Snakes[mySlot] != nil && !sg.State.Snakes[mySlot].Alive {
|
|
<div class="alert alert-error text-xl font-bold">You're out!</div>
|
|
} else if sg.Mode == snake.ModeSinglePlayer {
|
|
<div class="alert alert-success text-xl font-bold">
|
|
{ fmt.Sprintf("Score: %d", sg.Score) }
|
|
</div>
|
|
} else {
|
|
<div class="alert alert-success text-xl font-bold">Go!</div>
|
|
}
|
|
case snake.StatusFinished:
|
|
@finishedBanner(sg, mySlot, gameID)
|
|
}
|
|
</div>
|
|
}
|
|
|
|
templ finishedBanner(sg *snake.SnakeGame, mySlot int, gameID string) {
|
|
if sg.Mode == snake.ModeSinglePlayer {
|
|
<div class="alert alert-info text-xl font-bold">
|
|
{ fmt.Sprintf("Game Over! Score: %d", sg.Score) }
|
|
@rematchOrJoin(sg, gameID)
|
|
</div>
|
|
} else if sg.Winner != nil {
|
|
if sg.Winner.Slot == mySlot {
|
|
<div class="alert alert-success text-xl font-bold">
|
|
You win!
|
|
@rematchOrJoin(sg, gameID)
|
|
</div>
|
|
} else {
|
|
<div class="alert alert-error text-xl font-bold">
|
|
{ sg.Winner.Nickname + " wins!" }
|
|
@rematchOrJoin(sg, gameID)
|
|
</div>
|
|
}
|
|
} else {
|
|
<div class="alert alert-warning text-xl font-bold">
|
|
It's a draw!
|
|
@rematchOrJoin(sg, gameID)
|
|
</div>
|
|
}
|
|
}
|
|
|
|
templ rematchOrJoin(sg *snake.SnakeGame, gameID string) {
|
|
if sg.RematchGameID != nil {
|
|
<a class="btn btn-sm bg-white text-gray-800 border-none ml-4" href={ templ.SafeURL("/snake/" + *sg.RematchGameID) }>
|
|
Join Rematch
|
|
</a>
|
|
} else {
|
|
<button
|
|
class="btn btn-sm bg-white text-gray-800 border-none ml-4"
|
|
type="button"
|
|
data-on:click={ datastar.PostSSE("/snake/%s/rematch", gameID) }
|
|
>
|
|
Play again
|
|
</button>
|
|
}
|
|
}
|
|
|
|
templ PlayerList(sg *snake.SnakeGame, mySlot int) {
|
|
<div id="snake-players" class="flex flex-wrap gap-4 mb-2">
|
|
for i, p := range sg.Players {
|
|
if p != nil {
|
|
<div class="flex items-center gap-2">
|
|
<span style={ fmt.Sprintf("width:16px;height:16px;border-radius:50%%;background:%s;display:inline-block;", snakeColor(i)) }></span>
|
|
<span>
|
|
{ p.Nickname }
|
|
if i == mySlot {
|
|
{ " (You)" }
|
|
}
|
|
</span>
|
|
if sg.Status == snake.StatusInProgress || sg.Status == snake.StatusFinished {
|
|
if sg.State != nil && i < len(sg.State.Snakes) && sg.State.Snakes[i] != nil {
|
|
if sg.State.Snakes[i].Alive {
|
|
<span class="text-sm opacity-60">
|
|
{ fmt.Sprintf("(%d)", len(sg.State.Snakes[i].Body)) }
|
|
</span>
|
|
} else {
|
|
<span class="text-sm opacity-40">(dead)</span>
|
|
}
|
|
}
|
|
}
|
|
</div>
|
|
}
|
|
}
|
|
</div>
|
|
}
|
|
|
|
templ InviteLink(gameID string) {
|
|
{{ fullURL := config.Global.AppURL + "/snake/" + gameID }}
|
|
<div id="snake-invite" class="mt-4 text-center">
|
|
<p>Share this link to invite players:</p>
|
|
<div class="bg-base-200 p-4 rounded-lg font-mono break-all my-2">
|
|
{ fullURL }
|
|
</div>
|
|
<button
|
|
class="btn btn-sm mt-2"
|
|
type="button"
|
|
onclick={ copyToClipboard(fullURL) }
|
|
>
|
|
Copy Link
|
|
</button>
|
|
</div>
|
|
}
|
|
|
|
script copyToClipboard(url string) {
|
|
navigator.clipboard.writeText(url)
|
|
}
|