diff --git a/packages/wonders-client/package.json b/packages/wonders-client/package.json index 5f241d2..762dd0d 100644 --- a/packages/wonders-client/package.json +++ b/packages/wonders-client/package.json @@ -14,7 +14,6 @@ "formik": "^2.2.6", "ketchup-react": "^0.1.0", "react": "^17.0.2", - "react-bootstrap": "^1.6.0", "react-dom": "^17.0.2", "react-scripts": "4.0.3", "typescript": "^4.1.2", @@ -45,4 +44,4 @@ "last 1 safari version" ] } -} +} \ No newline at end of file diff --git a/packages/wonders-client/public/index.html b/packages/wonders-client/public/index.html index aa069f2..55cdd14 100644 --- a/packages/wonders-client/public/index.html +++ b/packages/wonders-client/public/index.html @@ -1,21 +1,19 @@ - - - - - - - - - - - React App - - - -
- - - + + + \ No newline at end of file diff --git a/packages/wonders-client/src/components/App/App.css b/packages/wonders-client/src/components/App/App.css index 74b5e05..af53574 100644 --- a/packages/wonders-client/src/components/App/App.css +++ b/packages/wonders-client/src/components/App/App.css @@ -1,38 +1,14 @@ -.App { - text-align: center; -} - -.App-logo { - height: 40vmin; - pointer-events: none; -} - -@media (prefers-reduced-motion: no-preference) { - .App-logo { - animation: App-logo-spin infinite 20s linear; - } -} - -.App-header { - background-color: #282c34; - min-height: 100vh; +.wonder-outer { display: flex; flex-direction: column; - align-items: center; - justify-content: center; - font-size: calc(10px + 2vmin); - color: white; + height: 100vh; } -.App-link { - color: #61dafb; +.wonder-top-bar { + display: flex; + justify-content: space-between; } -@keyframes App-logo-spin { - from { - transform: rotate(0deg); - } - to { - transform: rotate(360deg); - } +.wonder-game-wrapper { + overflow: auto; } diff --git a/packages/wonders-client/src/components/App/App.tsx b/packages/wonders-client/src/components/App/App.tsx index 349cdff..078b0f6 100644 --- a/packages/wonders-client/src/components/App/App.tsx +++ b/packages/wonders-client/src/components/App/App.tsx @@ -4,10 +4,6 @@ import { addPlayerAction, loadSampleAction, reducer, removePlayerAction, resetAc import './App.css' import Game from '../Game/Game' import UserSelector from '../UserSelector/UserSelector' -import 'bootstrap/dist/css/bootstrap.min.css' -import Container from 'react-bootstrap/Container' -import Row from 'react-bootstrap/Row' -import Col from 'react-bootstrap/Col' export default function App() { const [state, dispatch] = useKetchup('ws://localhost:4000', reducer) @@ -39,26 +35,20 @@ export default function App() { } } - return - - - p.name) ?? []} locked={state !== undefined && state.stage !== 'starting'} /> - - - {state - ? <> - - - - - - - {' '} - - - - - : Loading… - } - + return
+
+ p.name) ?? []} locked={state !== undefined && state.stage !== 'starting'} /> +
+ + {' '} + +
+
+
+ {state + ? + :
Loading…
+ } +
+
} diff --git a/packages/wonders-client/src/components/Civ/Civ.css b/packages/wonders-client/src/components/Civ/Civ.css index 104197a..baa9adf 100644 --- a/packages/wonders-client/src/components/Civ/Civ.css +++ b/packages/wonders-client/src/components/Civ/Civ.css @@ -1,20 +1,35 @@ -.wonder-civ-outer { +.wonder-civ { + border: black solid; + margin: 1em; + background-color: white; +} + +.wonder-civ-wonder { background-position: center; background-size: cover; - border: black solid; } -.wonder-civ-outer ol { +.wonder-civ-structs { + display: flex; +} +.wonder-civ-struct-col { + display: flex; + flex-direction: column; +} +.wonder-civ-struct-group { list-style-type: none; + padding-left: 0; + font-size: 0.8em; + width: 12em; } - .wonder-civ-struct { + border: thin black solid; font-weight: bold; } .wonder-civ-struct-type-commerce { background-color: yellow; color: black; } .wonder-civ-struct-type-culture { background-color: blue; color: white; } .wonder-civ-struct-type-science { background-color: green; color: white; } .wonder-civ-struct-type-basic-industry { background-color: brown; color: white; } -.wonder-civ-struct-type-advanced-industry { background-color: gray; color: black; } +.wonder-civ-struct-type-advanced-industry { background-color: lightgray; color: black; } .wonder-civ-struct-type-guild { background-color: purple; color: white; } .wonder-civ-struct-type-military { background-color: red; color: white; } diff --git a/packages/wonders-client/src/components/Civ/Civ.tsx b/packages/wonders-client/src/components/Civ/Civ.tsx index 9b64788..9b06b09 100644 --- a/packages/wonders-client/src/components/Civ/Civ.tsx +++ b/packages/wonders-client/src/components/Civ/Civ.tsx @@ -1,10 +1,9 @@ import { useMemo } from 'react' -import { Player, playerStats, Resource, Science, Structure, structureTypes } from 'wonders-common' +import { Player, playerStats, Resource, Science, Structure, StructureType, wonders } from 'wonders-common' import fill from 'lodash/fill' import './Civ.css' -import Container from 'react-bootstrap/Container' -import Row from 'react-bootstrap/Row' -import Col from 'react-bootstrap/Col' + +type DisplayStyle = 'player' | 'neighbor' | 'distant' const resEmojis = new Map([ ['brick', '🧱'], @@ -20,6 +19,21 @@ const sciEmojis = new Map([ ['engineering', '⚙️'], ['research', '📚'], ]) +const structTypeLayout = new Map([ + ['player', [ + ['basic industry'], ['advanced industry'], ['military'], ['science'], ['commerce'], ['guild'], ['culture'], + ]], + ['neighbor', [ + ['basic industry', 'advanced industry'], + ['military', 'science'], + ['commerce', 'guild', 'culture'], + ]], + ['distant', [ + ['basic industry', 'advanced industry', 'military'], + ['science', 'commerce', 'guild', 'culture'], + ]], +]) + const wonderBgExts = ['jpg', 'webp'] function structurePeek(struct: Structure): string { @@ -40,29 +54,32 @@ function structurePeek(struct: Structure): string { } } -export default function Civ({ player, civStyle }: { player: Player, civStyle: 'player' | 'neighbor' | 'compact' }) { +export default function Civ({ player, displayStyle }: { player: Player, displayStyle: DisplayStyle }) { const pStats = useMemo(() => playerStats(player), [player]) - const outerStyle: React.CSSProperties = player.wonder === undefined ? {} : { - backgroundImage: ['linear-gradient(to left, rgba(255, 255, 255, 0.25), rgba(255, 255, 255, 0.75))', ...wonderBgExts.map(ext => `url("/assets/wonders/${player.wonder}.${ext}")`)].join(', '), - } + const wonderBgImage = ['linear-gradient(to left, rgba(255, 255, 255, 0), rgba(255, 255, 255, 0.75))', ...wonderBgExts.map(ext => `url("/assets/wonders/${player.wonder}.${ext}")`)].join(', ') + const wonder = player.wonder ? wonders.get(player.wonder) : undefined - return - - {player.name}{player.wonder && ` • ${player.wonder}`} - - - {structureTypes.map(type => - -
    - {pStats.structObjs.filter(o => o.type === type).map((s, i) => -
  1. - {s.name} {structurePeek(s)} -
  2. - )} -
- + return
+
{player.name}
+
+
{player.wonder}
+
{resEmojis.get(wonder!.innateResource)}
+
+
+ {structTypeLayout.get(displayStyle)!.map((col, i) => +
+ {col.filter(type => pStats.structObjs.some(s => s.type === type)).map(type => +
    + {pStats.structObjs.filter(o => o.type === type).map((s, i) => +
  1. + {s.name} {structurePeek(s)} +
  2. + )} +
+ )} +
)} - - +
+
} diff --git a/packages/wonders-client/src/components/Game/Game.css b/packages/wonders-client/src/components/Game/Game.css new file mode 100644 index 0000000..c7fb389 --- /dev/null +++ b/packages/wonders-client/src/components/Game/Game.css @@ -0,0 +1,24 @@ +.wonder-game { + background-image: url(world.webp); + background-position: center; + background-size: cover; +} + +.wonder-lobby { + display: flex; + flex-flow: row wrap; +} + +.wonder-distant { + display: flex; + flex-flow: row nowrap; + justify-content: center; +} +.wonder-neighbors { + display: flex; + flex-flow: row nowrap; + justify-content: space-between; +} +.wonder-center { + align-self: center; +} diff --git a/packages/wonders-client/src/components/Game/Game.tsx b/packages/wonders-client/src/components/Game/Game.tsx index 15f8d4c..7e7185a 100644 --- a/packages/wonders-client/src/components/Game/Game.tsx +++ b/packages/wonders-client/src/components/Game/Game.tsx @@ -2,9 +2,8 @@ import { Dispatch } from 'ketchup-react' import { Action, chooseWonderAction, maxPlayers, minPlayers, Player, startGameAction, State, structures, wonders } from 'wonders-common' import Civ from '../Civ/Civ' import Card from '../Card/Card' -import Row from 'react-bootstrap/Row' -import Col from 'react-bootstrap/Col' import { ErrorMessage, Field, Form, Formik } from 'formik' +import './Game.css' function getDistant(arr: T[], idx: number) { switch (idx) { @@ -14,14 +13,6 @@ function getDistant(arr: T[], idx: number) { } } -function DistantCivs({ players }: { players: Player[] }) { - return {players.map(p => - - - - )} -} - export default function Game({ state, playerName, dispatch }: { state: State, playerName?: string, dispatch: Dispatch }) { const playerIdx: number | undefined = state.players.findIndex(p => p.name === playerName) const player: Player | undefined = state.players[playerIdx] @@ -35,34 +26,16 @@ export default function Game({ state, playerName, dispatch }: { state: State, pl return state.players.filter(p => p.name !== playerName).map(p => p.wonder).includes(wonder) } - if (!player) { - return - } else if (started) { - return <> - - - - -
{state.age === undefined ? '' : `Age ${state.age + 1} ${state.age % 2 === 0 ? '🔃' : '🔄'}`}
-
- - -
- - - - {player.hand?.map(s => structures.get(s)!)?.map(s => - - - - )} - - } else { - return <> - - - - + let gameElem: JSX.Element + if (!player || !started) { + gameElem =
+ {state.players.map(p => + + )} +
+ if (!started) { + gameElem = <> + {gameElem} { @@ -75,30 +48,51 @@ export default function Game({ state, playerName, dispatch }: { state: State, pl } return errors }} - onSubmit={({ wonder }) => dispatch(chooseWonderAction(player.name, wonder))} - >{() =>
- - {' '} - - {[...wonders.keys()].map(w => - - )} - - {' '} - - } + onSubmit={({ wonder }) => dispatch(chooseWonderAction(player.name, wonder))}> +
+ + {' '} + + {[...wonders.keys()].map(w => + + )} + + {' '} + +
-
- - - - {/* TODO Pick wonder */} +
+ +
+ + } + } else { + gameElem = <> +
+ {started.distant.map(p => + + )} +
+
+ +
+
{state.age === undefined ? '' : `Age ${state.age + 1} ${state.age % 2 === 0 ? '🔃' : '🔄'}`}
+
+
+ +
+ +
{player.hand?.map(s => structures.get(s)!)?.map((s, i) => + + )}
} + + return
{gameElem}
} diff --git a/packages/wonders-client/src/components/Game/world.webp b/packages/wonders-client/src/components/Game/world.webp new file mode 100644 index 0000000..efb2d67 Binary files /dev/null and b/packages/wonders-client/src/components/Game/world.webp differ diff --git a/packages/wonders-client/src/components/UserSelector/UserSelector.tsx b/packages/wonders-client/src/components/UserSelector/UserSelector.tsx index e87d579..d4144e8 100644 --- a/packages/wonders-client/src/components/UserSelector/UserSelector.tsx +++ b/packages/wonders-client/src/components/UserSelector/UserSelector.tsx @@ -1,8 +1,6 @@ import { ErrorMessage, Field, Form, Formik } from 'formik'; import { Dispatch, useState } from 'react'; import sample from 'lodash/sample' -import Row from 'react-bootstrap/Row'; -import Col from 'react-bootstrap/Col'; const namePlaceholders = [ 'Alexander the Great', @@ -20,9 +18,9 @@ export default function UserSelector({ users, user, selectUser, removeUser, lock users: string[], user?: string, selectUser: Dispatch, removeUser: () => void, locked: boolean }) { const [namePlaceholder] = useState(() => sample(namePlaceholders)) - return + return
{user - ? Playing as {user} + ? <>Playing as {user} : { @@ -44,5 +42,5 @@ export default function UserSelector({ users, user, selectUser, removeUser, lock } } - +
}