Add war display

This commit is contained in:
Kenneth Allen 2021-11-03 22:36:03 +11:00
parent e8cf27d65d
commit 132995c051
9 changed files with 127 additions and 8 deletions

View File

@ -10,12 +10,15 @@
"@types/node": "^16.11.4",
"@types/react": "^17.0.5",
"@types/react-dom": "^17.0.5",
"@types/roman-numerals": "^0.3.0",
"classnames": "^2.3.1",
"eslint-config-react-app": "^6.0.0",
"formik": "^2.2.6",
"ketchup-react": "^0.1.1",
"react": "^17.0.2",
"react-dom": "^17.0.2",
"react-scripts": "^4.0.3",
"roman-numerals": "^0.3.2",
"typescript": "^4.1.2",
"web-vitals": "^2.1.2",
"wonders-common": "^0.1.1"

View File

@ -11,4 +11,5 @@
.wonder-game-wrapper {
overflow: auto;
flex: 1;
}

View File

@ -1,6 +1,5 @@
.wonder-civ {
border: black solid;
margin: 1em;
background-color: white;
}

View File

@ -2,6 +2,7 @@ import { useMemo } from 'react'
import { Player, playerStats, Resource, Science, Structure, StructureType, wonders } from 'wonders-common'
import fill from 'lodash/fill'
import './Civ.css'
import classNames from 'classnames'
type DisplayStyle = 'player' | 'neighbor' | 'distant'
@ -72,7 +73,7 @@ export default function Civ({ player, displayStyle }: { player: Player, displayS
{col.filter(type => pStats.structObjs.some(s => s.type === type)).map(type =>
<ol key={type} className='wonder-civ-struct-group'>
{pStats.structObjs.filter(o => o.type === type).map((s, i) =>
<li key={i} className={`wonder-civ-struct wonder-civ-struct-type-${type.replaceAll(' ', '-')}`}>
<li key={i} className={classNames({ 'wonder-civ-struct': true, [`wonder-civ-struct-type-${type.replaceAll(' ', '-')}`]: true })}>
{s.name} {structurePeek(s)}
</li>
)}

View File

@ -2,21 +2,29 @@
background-image: url(world.webp);
background-position: center;
background-size: cover;
height: 100%;
}
.wonder-lobby {
display: flex;
flex-flow: row wrap;
flex-wrap: wrap;
}
.wonder-distant {
display: flex;
justify-content: center;
}
.wonder-neighbors {
display: flex;
justify-content: space-between;
}
.wonder-neighbor {
display: flex;
flex-flow: column;
justify-content: space-evenly;
}
.wonder-center {
align-self: center;
}

View File

@ -4,6 +4,9 @@ import Civ from '../Civ/Civ'
import Card from '../Card/Card'
import './Game.css'
import WonderSelector from '../WonderSelector/WonderSelector'
import War from '../War/War'
import first from 'lodash/first'
import last from 'lodash/last'
function getDistant<T>(arr: T[], idx: number) {
switch (idx) {
@ -45,19 +48,32 @@ export default function Game({ state, playerName, dispatch }: { state: State, pl
</>
}
} else {
console.log(player.name, player.leftBattles)
console.log(started.right.name, started.right.rightBattles)
gameElem = <>
<div className='wonder-distant'>
{started.distant.map(p =>
<War vertical players={[started.left, first(started.distant)!]} state={state} alignBottom />
{started.distant.map((p, i) =>
<>
<Civ key={p.name} player={p} displayStyle='distant' />
{i + 1 < started.distant.length && <War vertical players={started.distant.slice(i, i + 2)} state={state} />}
</>
)}
<War vertical players={[last(started.distant)!, started.right]} state={state} alignBottom />
</div>
<div className='wonder-neighbors'>
<div className='wonder-neighbor'>
<Civ player={started.left} displayStyle='neighbor' />
<War players={[started.left, player]} state={state} />
</div>
<div className='wonder-center'>
<div>{state.age === undefined ? '' : `Age ${state.age + 1} ${state.age % 2 === 0 ? '🔃' : '🔄'}`}</div>
<div><button>Discards</button></div>
</div>
<div className='wonder-neighbor'>
<Civ player={started.right} displayStyle='neighbor' />
<War players={[started.right, player]} state={state} />
</div>
</div>
<Civ player={player} displayStyle='player' />
<div>{player.hand?.map(s => structures.get(s)!)?.map((s, i) =>

View File

@ -0,0 +1,46 @@
.wonder-war {
display: flex;
background-color: lightcoral;
align-self: center;
justify-content: center;
font-family: serif;
text-align: center;
}
.wonder-war-vertical {
flex-direction: column;
}
.wonder-war-crossed-swords {
align-self: center;
}
.wonder-war-align-bottom {
align-self: flex-end;
}
.wonder-war-battle {
border: 1pt solid red;
margin: 0.1em;
padding: 0.1em;
display: flex;
align-items: center;
}
.wonder-war-vertical .wonder-war-battle {
flex-direction: column;
}
.wonder-war-battle-results {
display: flex;
justify-content: space-between;
}
.wonder-war-horizontal .wonder-war-battle-results {
flex-direction: column;
}
.wonder-war-battle-result {
background-color: red;
color: white;
margin: 0.2em;
min-width: 1.5em;
font-weight: bold;
}

View File

@ -0,0 +1,30 @@
import classNames from "classnames";
import { numAges, Player, State } from 'wonders-common'
import zip from 'lodash/zip'
import range from 'lodash/range'
import './War.css'
import { toRoman } from 'roman-numerals'
function Battle({ age, future, battle }: { age: number, future: boolean, battle: [number | undefined, number | undefined] }) {
function resultText(result?: number) {
return future ? '…' : result ?? '🕊️'
}
return <div className='wonder-war-battle'>
<div>{toRoman(age + 1)}</div>
<div className='wonder-war-battle-results'>
{range(2).map(i => <div className='wonder-war-battle-result' key={i}>{resultText(battle[i])}</div>)}
</div>
</div>
}
export default function War({ state, players, vertical, alignBottom }: { state: State, players: Player[], vertical?: boolean, alignBottom?: boolean }) {
let battles = zip(players[0].rightBattles, players[1].leftBattles)
console.log(players, vertical, battles)
return <div className={classNames({ 'wonder-war': true, 'wonder-war-vertical': vertical, 'wonder-war-horizontal': !vertical, 'wonder-war-align-bottom': alignBottom })}>
<div className='wonder-war-crossed-swords'></div>
{range(numAges).map(age => <Battle age={age} battle={battles[age] ?? []} future={age >= state.age!} key={age} />)}
</div>
}

View File

@ -2967,6 +2967,11 @@
dependencies:
"@types/node" "*"
"@types/roman-numerals@^0.3.0":
version "0.3.0"
resolved "https://registry.yarnpkg.com/@types/roman-numerals/-/roman-numerals-0.3.0.tgz#6e8ad8e7c0dc6e2d4f4d6aca9df6677f3b8e2282"
integrity sha512-sfO4vwDEH5hpm9GHQMkcJaRUWgcrlgJn9YLQv+6l9JBQk+Xe4nx9zfbHgS+3x1sMwZUnFc0sgTY0eAHr9Foqhw==
"@types/scheduler@*":
version "0.16.2"
resolved "https://registry.yarnpkg.com/@types/scheduler/-/scheduler-0.16.2.tgz#1a62f89525723dde24ba1b01b092bf5df8ad4d39"
@ -4668,6 +4673,11 @@ class-utils@^0.3.5:
isobject "^3.0.0"
static-extend "^0.1.1"
classnames@^2.3.1:
version "2.3.1"
resolved "https://registry.yarnpkg.com/classnames/-/classnames-2.3.1.tgz#dfcfa3891e306ec1dad105d0e88f4417b8535e8e"
integrity sha512-OlQdbZ7gLfGarSqxesMesDa5uz7KFbID8Kpq/SxIoNGDqY8lSYs0D+hhtBXhcdB3rcbXArFr7vlHheLk1voeNA==
clean-css@^4.2.3:
version "4.2.4"
resolved "https://registry.yarnpkg.com/clean-css/-/clean-css-4.2.4.tgz#733bf46eba4e607c6891ea57c24a989356831178"
@ -12781,6 +12791,11 @@ rollup@^1.31.1:
"@types/node" "*"
acorn "^7.1.0"
roman-numerals@^0.3.2:
version "0.3.2"
resolved "https://registry.yarnpkg.com/roman-numerals/-/roman-numerals-0.3.2.tgz#907ddf90c64e1b5dce8ed5e8fb0718318f2f26e6"
integrity sha1-kH3fkMZOG13OjtXo+wcYMY8vJuY=
rsvp@^4.8.4:
version "4.8.5"
resolved "https://registry.yarnpkg.com/rsvp/-/rsvp-4.8.5.tgz#c8f155311d167f68f21e168df71ec5b083113734"