style boost
This commit is contained in:
@@ -3,102 +3,105 @@
|
||||
|
||||
<article class="game-board">
|
||||
<!-- Game board -->
|
||||
<section class="board" data-perspective="@Perspective">
|
||||
<section class="board" data-perspective="@Perspective" style="grid-area: board">
|
||||
@for (var rank = 1; rank < 10; rank++)
|
||||
|
||||
{
|
||||
|
||||
foreach (var file in Files)
|
||||
|
||||
{
|
||||
|
||||
var position = $"{file}{rank}";
|
||||
|
||||
var piece = Session?.BoardState.Board[position];
|
||||
|
||||
var isSelected = piece != null && SelectedPosition == position;
|
||||
<div class="tile" @onclick="OnClickTileInternal(position)"
|
||||
data-position="@(position)"
|
||||
data-selected="@(isSelected)"
|
||||
style="grid-area: @position">
|
||||
@if (piece != null)
|
||||
|
||||
{
|
||||
<GamePiece Piece="piece" Perspective="Perspective" />
|
||||
}
|
||||
</div>
|
||||
}
|
||||
|
||||
}
|
||||
<div class="ruler vertical" style="grid-area: rank">
|
||||
<span>9</span>
|
||||
<span>8</span>
|
||||
<span>7</span>
|
||||
<span>6</span>
|
||||
<span>5</span>
|
||||
<span>4</span>
|
||||
<span>3</span>
|
||||
<span>2</span>
|
||||
<span>1</span>
|
||||
</div>
|
||||
<div class="ruler" style="grid-area: file">
|
||||
<span>A</span>
|
||||
<span>B</span>
|
||||
<span>C</span>
|
||||
<span>D</span>
|
||||
<span>E</span>
|
||||
<span>F</span>
|
||||
<span>G</span>
|
||||
<span>H</span>
|
||||
<span>I</span>
|
||||
</div>
|
||||
</section>
|
||||
<div class="ruler vertical" style="grid-area: rank">
|
||||
<span>9</span>
|
||||
<span>8</span>
|
||||
<span>7</span>
|
||||
<span>6</span>
|
||||
<span>5</span>
|
||||
<span>4</span>
|
||||
<span>3</span>
|
||||
<span>2</span>
|
||||
<span>1</span>
|
||||
</div>
|
||||
<div class="ruler" style="grid-area: file">
|
||||
<span>A</span>
|
||||
<span>B</span>
|
||||
<span>C</span>
|
||||
<span>D</span>
|
||||
<span>E</span>
|
||||
<span>F</span>
|
||||
<span>G</span>
|
||||
<span>H</span>
|
||||
<span>I</span>
|
||||
</div>
|
||||
|
||||
<!-- Side board -->
|
||||
@if (Session != null && UseSideboard == true)
|
||||
|
||||
{
|
||||
<aside class="side-board PrimaryTheme ThemeVariant--Contrast">
|
||||
<div class="player-area">
|
||||
<div class="hand">
|
||||
@if (opponentHand.Any())
|
||||
{
|
||||
@foreach (var piece in opponentHand)
|
||||
{
|
||||
<div class="tile">
|
||||
<GamePiece Piece="piece" Perspective="Perspective" />
|
||||
</div>
|
||||
}
|
||||
}
|
||||
</div>
|
||||
<p class="text-center">Opponent's Hand</p>
|
||||
</div>
|
||||
|
||||
<div class="place-self-center">
|
||||
<PlayerName Name="@opponentName" IsTurn="!IsMyTurn" InCheck="IsOpponentInCheck" IsVictor="IsOpponentVictor" />
|
||||
<hr />
|
||||
<PlayerName Name="@userName" IsTurn="IsMyTurn" InCheck="IsPlayerInCheck" IsVictor="IsPlayerVictor" />
|
||||
</div>
|
||||
|
||||
<div class="player-area">
|
||||
@if (Perspective == WhichPlayer.Player2 && string.IsNullOrEmpty(Session.Player2))
|
||||
<aside class="side-board opponent PrimaryTheme ThemeVariant--Contrast" style="grid-area: opponent-side-board">
|
||||
@if (opponentHand.Any())
|
||||
{
|
||||
@foreach (var piece in opponentHand)
|
||||
{
|
||||
<AuthorizeView>
|
||||
<div class="place-self-center">
|
||||
<button @onclick="OnClickJoinGameInternal">Join Game</button>
|
||||
</div>
|
||||
</AuthorizeView>
|
||||
}
|
||||
else
|
||||
{
|
||||
<p class="text-center">Your Hand</p>
|
||||
<div class="hand">
|
||||
@if (userHand.Any())
|
||||
{
|
||||
@foreach (var piece in userHand)
|
||||
{
|
||||
<div @onclick="OnClickHandInternal(piece)"
|
||||
class="tile"
|
||||
data-selected="@(piece.WhichPiece == SelectedPieceFromHand)">
|
||||
<GamePiece Piece="piece" Perspective="Perspective" />
|
||||
</div>
|
||||
}
|
||||
}
|
||||
<div class="tile">
|
||||
<GamePiece Piece="piece" Perspective="Perspective" />
|
||||
</div>
|
||||
}
|
||||
</div>
|
||||
}
|
||||
</aside>
|
||||
|
||||
<div class="player-info" style="grid-area: player-info">
|
||||
<OpponentName Name="@opponentName"
|
||||
IsTurn="!IsMyTurn"
|
||||
InCheck="IsOpponentInCheck"
|
||||
IsVictor="IsOpponentVictor" />
|
||||
<PlayerName Name="@userName"
|
||||
IsTurn="IsMyTurn"
|
||||
InCheck="IsPlayerInCheck"
|
||||
IsVictor="IsPlayerVictor" />
|
||||
</div>
|
||||
|
||||
<aside class="side-board PrimaryTheme ThemeVariant--Contrast" style="grid-area: player-side-board">
|
||||
@if (Perspective == WhichPlayer.Player2 && string.IsNullOrEmpty(Session.Player2))
|
||||
{
|
||||
<AuthorizeView>
|
||||
<div class="place-self-center">
|
||||
<button @onclick="OnClickJoinGameInternal">Join Game</button>
|
||||
</div>
|
||||
</AuthorizeView>
|
||||
}
|
||||
else if (userHand.Any())
|
||||
{
|
||||
@foreach (var piece in userHand)
|
||||
|
||||
{
|
||||
<div @onclick="OnClickHandInternal(piece)"
|
||||
class="tile"
|
||||
data-selected="@(piece.WhichPiece == SelectedPieceFromHand)">
|
||||
<GamePiece Piece="piece" Perspective="Perspective" />
|
||||
</div>
|
||||
}
|
||||
}
|
||||
</aside>
|
||||
}
|
||||
</article>
|
||||
@@ -119,12 +122,10 @@
|
||||
[Parameter] public EventCallback<Piece> OnClickHand { get; set; }
|
||||
[Parameter] public EventCallback OnClickJoinGame { get; set; }
|
||||
[Parameter] public bool UseSideboard { get; set; } = true;
|
||||
|
||||
private IReadOnlyCollection<Piece> opponentHand;
|
||||
private IReadOnlyCollection<Piece> userHand;
|
||||
private string? userName;
|
||||
private string? opponentName;
|
||||
|
||||
public GameBoardPresentation()
|
||||
{
|
||||
opponentHand = Array.Empty<Piece>();
|
||||
@@ -136,6 +137,7 @@
|
||||
protected override void OnParametersSet()
|
||||
{
|
||||
base.OnParametersSet();
|
||||
|
||||
if (Session == null)
|
||||
{
|
||||
opponentHand = Array.Empty<Piece>();
|
||||
@@ -161,16 +163,10 @@
|
||||
}
|
||||
|
||||
private bool IsMyTurn => Session?.BoardState.WhoseTurn == Perspective;
|
||||
|
||||
private bool IsPlayerInCheck => Session?.BoardState.PlayerInCheck == Perspective;
|
||||
|
||||
private bool IsOpponentInCheck => Session?.BoardState.PlayerInCheck != null && Session.BoardState.PlayerInCheck != Perspective;
|
||||
|
||||
private bool IsPlayerVictor => Session?.BoardState.Victor == Perspective;
|
||||
|
||||
|
||||
private bool IsOpponentVictor => Session?.BoardState.Victor != null && Session.BoardState.Victor != Perspective;
|
||||
|
||||
private Func<Task> OnClickTileInternal(string position) => () =>
|
||||
{
|
||||
if (IsMyTurn)
|
||||
@@ -179,7 +175,6 @@
|
||||
}
|
||||
return Task.CompletedTask;
|
||||
};
|
||||
|
||||
private Func<Task> OnClickHandInternal(Piece piece) => () =>
|
||||
{
|
||||
if (IsMyTurn)
|
||||
|
||||
@@ -1,47 +1,50 @@
|
||||
.game-board {
|
||||
--ratio: 0.9;
|
||||
display: grid;
|
||||
grid-template-columns: min-content repeat(9, minmax(2rem, 4rem)) max-content;
|
||||
grid-template-rows: repeat(9, 1fr) auto;
|
||||
grid-template-areas:
|
||||
"rank board opponent-side-board"
|
||||
"rank board player-info"
|
||||
"rank board player-side-board"
|
||||
". file .";
|
||||
grid-template-columns: auto 1fr auto;
|
||||
grid-template-rows: repeat(3, 1fr) auto;
|
||||
background-color: #444;
|
||||
gap: 3px;
|
||||
gap: 5px;
|
||||
place-self: center;
|
||||
color: beige;
|
||||
}
|
||||
|
||||
.board {
|
||||
display: grid;
|
||||
grid-column: span 10;
|
||||
grid-row: span 10;
|
||||
grid-template-areas:
|
||||
"rank A9 B9 C9 D9 E9 F9 G9 H9 I9"
|
||||
"rank A8 B8 C8 D8 E8 F8 G8 H8 I8"
|
||||
"rank A7 B7 C7 D7 E7 F7 G7 H7 I7"
|
||||
"rank A6 B6 C6 D6 E6 F6 G6 H6 I6"
|
||||
"rank A5 B5 C5 D5 E5 F5 G5 H5 I5"
|
||||
"rank A4 B4 C4 D4 E4 F4 G4 H4 I4"
|
||||
"rank A3 B3 C3 D3 E3 F3 G3 H3 I3"
|
||||
"rank A2 B2 C2 D2 E2 F2 G2 H2 I2"
|
||||
"rank A1 B1 C1 D1 E1 F1 G1 H1 I1"
|
||||
". file file file file file file file file file";
|
||||
grid-template-columns: subgrid;
|
||||
grid-template-rows: subgrid;
|
||||
"A9 B9 C9 D9 E9 F9 G9 H9 I9"
|
||||
"A8 B8 C8 D8 E8 F8 G8 H8 I8"
|
||||
"A7 B7 C7 D7 E7 F7 G7 H7 I7"
|
||||
"A6 B6 C6 D6 E6 F6 G6 H6 I6"
|
||||
"A5 B5 C5 D5 E5 F5 G5 H5 I5"
|
||||
"A4 B4 C4 D4 E4 F4 G4 H4 I4"
|
||||
"A3 B3 C3 D3 E3 F3 G3 H3 I3"
|
||||
"A2 B2 C2 D2 E2 F2 G2 H2 I2"
|
||||
"A1 B1 C1 D1 E1 F1 G1 H1 I1";
|
||||
grid-template-columns: repeat(9, 1fr);
|
||||
grid-template-rows: repeat(9, 1fr);
|
||||
background-color: #444444;
|
||||
max-height: 100%;
|
||||
gap: 3px;
|
||||
max-height: 80vmin;
|
||||
aspect-ratio: var(--ratio);
|
||||
}
|
||||
|
||||
.board[data-perspective="Player2"] {
|
||||
grid-template-areas:
|
||||
"rank I1 H1 G1 F1 E1 D1 C1 B1 A1"
|
||||
"rank I2 H2 G2 F2 E2 D2 C2 B2 A2"
|
||||
"rank I3 H3 G3 F3 E3 D3 C3 B3 A3"
|
||||
"rank I4 H4 G4 F4 E4 D4 C4 B4 A4"
|
||||
"rank I5 H5 G5 F5 E5 D5 C5 B5 A5"
|
||||
"rank I6 H6 G6 F6 E6 D6 C6 B6 A6"
|
||||
"rank I7 H7 G7 F7 E7 D7 C7 B7 A7"
|
||||
"rank I8 H8 G8 F8 E8 D8 C8 B8 A8"
|
||||
"rank I9 H9 G9 F9 E9 D9 C9 B9 A9"
|
||||
". file file file file file file file file file";
|
||||
"I1 H1 G1 F1 E1 D1 C1 B1 A1"
|
||||
"I2 H2 G2 F2 E2 D2 C2 B2 A2"
|
||||
"I3 H3 G3 F3 E3 D3 C3 B3 A3"
|
||||
"I4 H4 G4 F4 E4 D4 C4 B4 A4"
|
||||
"I5 H5 G5 F5 E5 D5 C5 B5 A5"
|
||||
"I6 H6 G6 F6 E6 D6 C6 B6 A6"
|
||||
"I7 H7 G7 F7 E7 D7 C7 B7 A7"
|
||||
"I8 H8 G8 F8 E8 D8 C8 B8 A8"
|
||||
"I9 H9 G9 F9 E9 D9 C9 B9 A9";
|
||||
}
|
||||
|
||||
|
||||
@@ -77,37 +80,41 @@
|
||||
}
|
||||
|
||||
.side-board {
|
||||
grid-row: span 9;
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
place-content: space-between;
|
||||
padding: 1rem;
|
||||
display: grid;
|
||||
grid-template-columns: repeat(auto-fill, 3rem);
|
||||
place-items: end start;
|
||||
gap: 5px;
|
||||
padding: 0.25rem;
|
||||
background: linear-gradient(45deg, beige, white);
|
||||
}
|
||||
|
||||
.side-board .player-area {
|
||||
display: grid;
|
||||
place-items: stretch;
|
||||
.side-board.opponent {
|
||||
place-items: start;
|
||||
}
|
||||
|
||||
.side-board .hand {
|
||||
display: grid;
|
||||
border: 1px solid #ccc;
|
||||
grid-template-columns: repeat(auto-fill, 3rem);
|
||||
grid-template-rows: 3rem;
|
||||
place-items: center start;
|
||||
padding: 0.5rem;
|
||||
.side-board:empty {
|
||||
content: 'Captured Pieces';
|
||||
}
|
||||
|
||||
.player-info {
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
justify-content: space-around;
|
||||
align-content: stretch;
|
||||
}
|
||||
|
||||
@media all and (max-width: 1000px) {
|
||||
@media all and (max-width: 900px) {
|
||||
.game-board {
|
||||
grid-template-columns: min-content repeat(9, minmax(2rem, 4rem));
|
||||
grid-template-rows: repeat(9, 1fr) auto max-content;
|
||||
grid-template-areas:
|
||||
". opponent-side-board ."
|
||||
"rank board player-info"
|
||||
". file ."
|
||||
". player-side-board .";
|
||||
grid-template-rows: auto 1fr auto auto;
|
||||
gap: 1rem;
|
||||
}
|
||||
|
||||
.side-board {
|
||||
grid-row: unset;
|
||||
grid-column: span 10;
|
||||
flex-direction: row;
|
||||
min-height: 2rem;
|
||||
}
|
||||
}
|
||||
|
||||
38
Shogi.UI/Pages/Play/GameBoard/OpponentName.razor
Normal file
38
Shogi.UI/Pages/Play/GameBoard/OpponentName.razor
Normal file
@@ -0,0 +1,38 @@
|
||||
@using Shogi.Contracts.Types
|
||||
<div style="margin: 0" class="PrimaryTheme">
|
||||
|
||||
@if (IsTurn)
|
||||
{
|
||||
<span class="turn-marker" title="Shows which player is next to move a piece.">Turn</span>
|
||||
<span> </span>
|
||||
}
|
||||
|
||||
@if (InCheck)
|
||||
{
|
||||
<span class="check-marker" title="King is in danger!">Check</span>
|
||||
<span> </span>
|
||||
}
|
||||
|
||||
@if (IsVictor)
|
||||
{
|
||||
<span class="victory-marker" title="Victory!">Victor</span>
|
||||
<span> </span>
|
||||
}
|
||||
|
||||
@if (string.IsNullOrEmpty(Name))
|
||||
{
|
||||
<div>Empty Seat</div>
|
||||
}
|
||||
else
|
||||
{
|
||||
<div>@Name</div>
|
||||
}
|
||||
|
||||
</div>
|
||||
|
||||
@code {
|
||||
[Parameter][EditorRequired] public bool IsTurn { get; set; }
|
||||
[Parameter][EditorRequired] public bool InCheck { get; set; }
|
||||
[Parameter][EditorRequired] public bool IsVictor { get; set; }
|
||||
[Parameter][EditorRequired] public string Name { get; set; } = string.Empty;
|
||||
}
|
||||
28
Shogi.UI/Pages/Play/GameBoard/OpponentName.razor.css
Normal file
28
Shogi.UI/Pages/Play/GameBoard/OpponentName.razor.css
Normal file
@@ -0,0 +1,28 @@
|
||||
.turn-marker {
|
||||
display: inline-block;
|
||||
padding: 2px 5px;
|
||||
background-color: var(--foregroundColor);
|
||||
background-color: var(--middlegroundColor);
|
||||
color: var(--backgroundColor);
|
||||
font-weight: bold;
|
||||
font-size: 80%;
|
||||
border-radius: 8px;
|
||||
}
|
||||
|
||||
.check-marker {
|
||||
display: inline-block;
|
||||
padding: 3px 8px;
|
||||
background-color: darkred;
|
||||
color: beige;
|
||||
font-weight: bold;
|
||||
font-size: 80%;
|
||||
}
|
||||
|
||||
.victory-marker {
|
||||
display: inline-block;
|
||||
padding: 3px 8px;
|
||||
background-color: darkgreen;
|
||||
color: beige;
|
||||
font-weight: bold;
|
||||
font-size: 80%;
|
||||
}
|
||||
@@ -1,4 +1,15 @@
|
||||
<p style="margin: 0">
|
||||
@using Shogi.Contracts.Types
|
||||
<div style="margin: 0" class="PrimaryTheme">
|
||||
|
||||
@if (string.IsNullOrEmpty(Name))
|
||||
{
|
||||
<div>Empty Seat</div>
|
||||
}
|
||||
else
|
||||
{
|
||||
<div>@Name</div>
|
||||
}
|
||||
|
||||
@if (IsTurn)
|
||||
{
|
||||
<span class="turn-marker" title="Shows which player is next to move a piece.">Turn</span>
|
||||
@@ -16,17 +27,7 @@
|
||||
<span class="victory-marker" title="Victory!">Victor</span>
|
||||
<span> </span>
|
||||
}
|
||||
|
||||
@if (string.IsNullOrEmpty(Name))
|
||||
{
|
||||
<span>Empty Seat</span>
|
||||
}
|
||||
else
|
||||
{
|
||||
<span>@Name</span>
|
||||
}
|
||||
|
||||
</p>
|
||||
</div>
|
||||
|
||||
@code {
|
||||
[Parameter][EditorRequired] public bool IsTurn { get; set; }
|
||||
|
||||
@@ -1,26 +1,30 @@
|
||||
.turn-marker {
|
||||
display: inline-block;
|
||||
padding: 3px 8px;
|
||||
background-color: #444;
|
||||
color: beige;
|
||||
padding: 2px 5px;
|
||||
background-color: var(--foregroundColor);
|
||||
background-color: var(--middlegroundColor);
|
||||
color: var(--backgroundColor);
|
||||
font-weight: bold;
|
||||
font-size: 80%;
|
||||
border-radius: 8px;
|
||||
}
|
||||
|
||||
.check-marker {
|
||||
display: inline-block;
|
||||
padding: 3px 8px;
|
||||
background-color: darkred;
|
||||
color: beige;
|
||||
padding: 2px 5px;
|
||||
background-color: #f3a1a1;
|
||||
color: darkred;
|
||||
font-weight: bold;
|
||||
font-size: 80%;
|
||||
border-radius: 8px;
|
||||
}
|
||||
|
||||
.victory-marker {
|
||||
display: inline-block;
|
||||
padding: 3px 8px;
|
||||
padding: 2px 5px;
|
||||
background-color: darkgreen;
|
||||
color: beige;
|
||||
color: white;
|
||||
font-weight: bold;
|
||||
font-size: 80%;
|
||||
border-radius: 8px;
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user