mirror of
https://github.com/Vikeo/LifeTrinket.git
synced 2025-11-13 22:56:20 +00:00
create health component
This commit is contained in:
@@ -127,6 +127,10 @@ export const CommanderDamage = ({
|
||||
const [timeoutFinished, setTimeoutFinished] = useState(false);
|
||||
const [hasPressedDown, setHasPressedDown] = useState(false);
|
||||
|
||||
const isSide =
|
||||
player.settings.rotation === Rotation.Side ||
|
||||
player.settings.rotation === Rotation.SideFlipped;
|
||||
|
||||
const handleCommanderDamageChange = (
|
||||
index: number,
|
||||
increment: number,
|
||||
@@ -189,9 +193,9 @@ export const CommanderDamage = ({
|
||||
};
|
||||
|
||||
const opponentIndex = opponent.index;
|
||||
const fontSize = '6vmin';
|
||||
const fontSize = isSide ? '4vmax' : '7vmin';
|
||||
const fontWeight = 'bold';
|
||||
const strokeWidth = '0.5vmin';
|
||||
const strokeWidth = isSide ? '0.4vmax' : '0.7vmin';
|
||||
|
||||
return (
|
||||
<CommanderDamageContainer
|
||||
|
||||
@@ -29,24 +29,6 @@ export const StyledExtraCounterButton = styled.button`
|
||||
height: 100%;
|
||||
`;
|
||||
|
||||
export const CenteredText = styled.div`
|
||||
position: absolute;
|
||||
top: 50%;
|
||||
left: 50%;
|
||||
transform: translate(-50%, -50%);
|
||||
font-size: 6vmin;
|
||||
font-weight: bold;
|
||||
-webkit-text-stroke: 0.4vmin #ffffff;
|
||||
-webkit-text-fill-color: #000000;
|
||||
color: #b5b2b2;
|
||||
user-select: none;
|
||||
-webkit-touch-callout: none;
|
||||
-webkit-tap-highlight-color: transparent;
|
||||
-moz-user-select: -moz-none;
|
||||
-webkit-user-select: none;
|
||||
-ms-user-select: none;
|
||||
`;
|
||||
|
||||
const IconContainer = styled.div<{
|
||||
rotation: number;
|
||||
}>`
|
||||
@@ -64,6 +46,13 @@ const IconContainer = styled.div<{
|
||||
}}
|
||||
`;
|
||||
|
||||
const TextContainer = styled.div`
|
||||
position: absolute;
|
||||
translate: -50%;
|
||||
top: 50%;
|
||||
left: 50%;
|
||||
`;
|
||||
|
||||
type ExtraCounterProps = {
|
||||
Icon: ReactNode;
|
||||
counterTotal?: number;
|
||||
@@ -83,6 +72,9 @@ const ExtraCounter = ({
|
||||
const [timeoutFinished, setTimeoutFinished] = useState(false);
|
||||
const [hasPressedDown, setHasPressedDown] = useState(false);
|
||||
|
||||
const isSide =
|
||||
rotation === Rotation.Side || rotation === Rotation.SideFlipped;
|
||||
|
||||
const handleCountChange = (increment: number) => {
|
||||
if (!counterTotal) {
|
||||
setCounterTotal(increment, type);
|
||||
@@ -115,6 +107,10 @@ const ExtraCounter = ({
|
||||
setHasPressedDown(false);
|
||||
};
|
||||
|
||||
const fontSize = isSide ? '4vmax' : '7vmin';
|
||||
const fontWeight = 'bold';
|
||||
const strokeWidth = isSide ? '0.4vmax' : '0.7vmin';
|
||||
|
||||
return (
|
||||
<ExtraCounterContainer>
|
||||
<StyledExtraCounterButton
|
||||
@@ -127,13 +123,15 @@ const ExtraCounter = ({
|
||||
>
|
||||
<IconContainer rotation={rotation}>
|
||||
{Icon}
|
||||
<TextContainer>
|
||||
<OutlinedText
|
||||
fontSize="6vmin"
|
||||
fontWeight="bold"
|
||||
strokeWidth="0.6vmin"
|
||||
fontSize={fontSize}
|
||||
fontWeight={fontWeight}
|
||||
strokeWidth={strokeWidth}
|
||||
>
|
||||
{counterTotal ? counterTotal : undefined}
|
||||
</OutlinedText>
|
||||
</TextContainer>
|
||||
</IconContainer>
|
||||
</StyledExtraCounterButton>
|
||||
</ExtraCounterContainer>
|
||||
|
||||
@@ -23,10 +23,6 @@ export const StyledLifeCounterButton = styled.button`
|
||||
-moz-user-select: -moz-none;
|
||||
-webkit-user-select: none;
|
||||
-ms-user-select: none;
|
||||
@media (orientation: landscape) {
|
||||
max-width: 50vmin;
|
||||
max-height: 50vmax;
|
||||
}
|
||||
`;
|
||||
|
||||
const TextContainer = styled.div<{
|
||||
@@ -34,7 +30,6 @@ const TextContainer = styled.div<{
|
||||
rotation: number;
|
||||
}>`
|
||||
position: relative;
|
||||
top: -10%;
|
||||
|
||||
${(props) => {
|
||||
if (
|
||||
@@ -45,13 +40,11 @@ const TextContainer = styled.div<{
|
||||
return css`
|
||||
rotate: -90deg;
|
||||
bottom: 25%;
|
||||
left: -10%;
|
||||
top: auto;
|
||||
`;
|
||||
}
|
||||
return css`
|
||||
rotate: -90deg;
|
||||
left: -10%;
|
||||
top: 25%;
|
||||
`;
|
||||
}
|
||||
@@ -117,7 +110,7 @@ const LifeCounterButton = ({
|
||||
const fontSize =
|
||||
rotation === Rotation.SideFlipped || rotation === Rotation.Side
|
||||
? '8vmax'
|
||||
: '16vmin';
|
||||
: '12vmin';
|
||||
|
||||
return (
|
||||
<StyledLifeCounterButton
|
||||
|
||||
@@ -1,4 +1,5 @@
|
||||
import { Player } from '../../Types/Player';
|
||||
import { WakeLock } from '../../Types/WakeLock';
|
||||
import LifeCounter from '../LifeCounter/LifeCounter';
|
||||
import styled from 'styled-components';
|
||||
|
||||
@@ -40,6 +41,7 @@ type CountersProps = {
|
||||
onPlayerChange: (updatedPlayer: Player) => void;
|
||||
gridAreas: string;
|
||||
resetCurrentGame: () => void;
|
||||
wakeLock: WakeLock;
|
||||
};
|
||||
|
||||
const Counters = ({
|
||||
@@ -47,6 +49,7 @@ const Counters = ({
|
||||
onPlayerChange,
|
||||
gridAreas,
|
||||
resetCurrentGame,
|
||||
wakeLock,
|
||||
}: CountersProps) => {
|
||||
return (
|
||||
<CountersWrapper>
|
||||
@@ -65,6 +68,7 @@ const Counters = ({
|
||||
)}
|
||||
onPlayerChange={onPlayerChange}
|
||||
resetCurrentGame={resetCurrentGame}
|
||||
wakeLock={wakeLock}
|
||||
/>
|
||||
</GridItemContainer>
|
||||
);
|
||||
|
||||
@@ -11,15 +11,31 @@ import {
|
||||
Poison,
|
||||
} from '../../Icons/generated';
|
||||
|
||||
const Container = styled.div<{ rotation: number }>`
|
||||
width: 100%;
|
||||
height: 20vmin;
|
||||
display: flex;
|
||||
|
||||
${(props) => {
|
||||
if (
|
||||
props.rotation === Rotation.SideFlipped ||
|
||||
props.rotation === Rotation.Side
|
||||
) {
|
||||
return css`
|
||||
height: 100%;
|
||||
width: 9.3vmax;
|
||||
`;
|
||||
}
|
||||
}}
|
||||
`;
|
||||
|
||||
const ExtraCountersGrid = styled.div<{ rotation: number }>`
|
||||
display: flex;
|
||||
position: absolute;
|
||||
width: 100%;
|
||||
flex-direction: row;
|
||||
flex-grow: 1;
|
||||
width: 100%;
|
||||
justify-content: space-evenly;
|
||||
bottom: 0;
|
||||
width: 100%;
|
||||
pointer-events: none;
|
||||
|
||||
${(props) => {
|
||||
@@ -81,11 +97,31 @@ const ExtraCountersBar = ({
|
||||
onPlayerChange(updatedPlayer);
|
||||
};
|
||||
|
||||
const iconSize = '8vmin';
|
||||
const iconSize =
|
||||
player.settings.rotation === Rotation.SideFlipped ||
|
||||
player.settings.rotation === Rotation.Side
|
||||
? '5vmax'
|
||||
: '10vmin';
|
||||
|
||||
const {
|
||||
useCommanderDamage,
|
||||
usePartner,
|
||||
usePoison,
|
||||
useEnergy,
|
||||
useExperience,
|
||||
} = player.settings;
|
||||
|
||||
const hasExtraCounters =
|
||||
useCommanderDamage || usePartner || usePoison || useEnergy || useExperience;
|
||||
|
||||
if (!hasExtraCounters) {
|
||||
return null;
|
||||
}
|
||||
|
||||
return (
|
||||
<Container rotation={player.settings.rotation}>
|
||||
<ExtraCountersGrid rotation={player.settings.rotation}>
|
||||
{player.settings.useCommanderDamage && (
|
||||
{useCommanderDamage && (
|
||||
<ExtraCounter
|
||||
rotation={player.settings.rotation}
|
||||
Icon={<CommanderTax size={iconSize} opacity="0.5" color="black" />}
|
||||
@@ -98,9 +134,7 @@ const ExtraCountersBar = ({
|
||||
setCounterTotal={handleCounterChange}
|
||||
/>
|
||||
)}
|
||||
{Boolean(
|
||||
player.settings.useCommanderDamage && player.settings.usePartner
|
||||
) && (
|
||||
{Boolean(useCommanderDamage && usePartner) && (
|
||||
<ExtraCounter
|
||||
rotation={player.settings.rotation}
|
||||
Icon={<PartnerTax size={iconSize} opacity="0.5" color="black" />}
|
||||
@@ -113,7 +147,7 @@ const ExtraCountersBar = ({
|
||||
setCounterTotal={handleCounterChange}
|
||||
/>
|
||||
)}
|
||||
{player.settings.usePoison && (
|
||||
{usePoison && (
|
||||
<ExtraCounter
|
||||
rotation={player.settings.rotation}
|
||||
Icon={<Poison size={iconSize} opacity="0.5" color="black" />}
|
||||
@@ -125,7 +159,7 @@ const ExtraCountersBar = ({
|
||||
setCounterTotal={handleCounterChange}
|
||||
/>
|
||||
)}
|
||||
{player.settings.useEnergy && (
|
||||
{useEnergy && (
|
||||
<ExtraCounter
|
||||
rotation={player.settings.rotation}
|
||||
Icon={<Energy size={iconSize} opacity="0.5" color="black" />}
|
||||
@@ -137,7 +171,7 @@ const ExtraCountersBar = ({
|
||||
setCounterTotal={handleCounterChange}
|
||||
/>
|
||||
)}
|
||||
{player.settings.useExperience && (
|
||||
{useExperience && (
|
||||
<ExtraCounter
|
||||
rotation={player.settings.rotation}
|
||||
Icon={<Experience size={iconSize} opacity="0.5" color="black" />}
|
||||
@@ -151,6 +185,7 @@ const ExtraCountersBar = ({
|
||||
/>
|
||||
)}
|
||||
</ExtraCountersGrid>
|
||||
</Container>
|
||||
);
|
||||
};
|
||||
|
||||
|
||||
234
src/Components/LifeCounter/Health.tsx
Normal file
234
src/Components/LifeCounter/Health.tsx
Normal file
@@ -0,0 +1,234 @@
|
||||
import { useEffect, useRef, useState } from 'react';
|
||||
import styled, { css, keyframes } from 'styled-components';
|
||||
import { Player, Rotation } from '../../Types/Player';
|
||||
import LifeCounterButton from '../Buttons/LifeCounterButton';
|
||||
import { OutlinedText } from '../Misc/OutlinedText';
|
||||
|
||||
const LifeCountainer = styled.div<{
|
||||
rotation: Rotation;
|
||||
}>`
|
||||
position: relative;
|
||||
display: flex;
|
||||
flex-direction: row;
|
||||
flex-grow: 1;
|
||||
width: 100%;
|
||||
height: 100%;
|
||||
justify-content: space-between;
|
||||
align-items: center;
|
||||
|
||||
${(props) => {
|
||||
if (
|
||||
props.rotation === Rotation.SideFlipped ||
|
||||
props.rotation === Rotation.Side
|
||||
) {
|
||||
return css`
|
||||
flex-direction: column-reverse;
|
||||
`;
|
||||
}
|
||||
}}
|
||||
`;
|
||||
|
||||
const LifeCounterTextContainer = styled.div<{
|
||||
rotation: Rotation;
|
||||
}>`
|
||||
position: absolute;
|
||||
width: 60%;
|
||||
height: 100%;
|
||||
margin: 0;
|
||||
padding: 0;
|
||||
pointer-events: none;
|
||||
-webkit-touch-callout: none;
|
||||
-webkit-tap-highlight-color: transparent;
|
||||
user-select: none;
|
||||
-moz-user-select: -moz-none;
|
||||
-webkit-user-select: none;
|
||||
-ms-user-select: none;
|
||||
|
||||
${(props) => {
|
||||
if (
|
||||
props.rotation === Rotation.SideFlipped ||
|
||||
props.rotation === Rotation.Side
|
||||
) {
|
||||
return css`
|
||||
width: 100%;
|
||||
height: 60%;
|
||||
`;
|
||||
}
|
||||
}}
|
||||
`;
|
||||
|
||||
const TextWrapper = styled.div`
|
||||
display: flex;
|
||||
position: absolute;
|
||||
justify-content: center;
|
||||
align-items: center;
|
||||
width: 100%;
|
||||
height: 100%;
|
||||
z-index: -1;
|
||||
`;
|
||||
|
||||
const fadeOut = keyframes`
|
||||
0% {
|
||||
opacity: 1;
|
||||
}
|
||||
33% {
|
||||
opacity: 0.6;
|
||||
}
|
||||
100% {
|
||||
opacity: 0;
|
||||
}
|
||||
`;
|
||||
|
||||
export const RecentDifference = styled.span`
|
||||
position: absolute;
|
||||
top: 40%;
|
||||
left: 50%;
|
||||
transform: translate(-50%, -50%);
|
||||
text-shadow: none;
|
||||
background-color: rgba(255, 255, 255, 0.6);
|
||||
font-variant-numeric: tabular-nums;
|
||||
border-radius: 50%;
|
||||
padding: 5px 10px;
|
||||
font-size: 8vmin;
|
||||
color: #333333;
|
||||
animation: ${fadeOut} 3s 1s ease-out forwards;
|
||||
`;
|
||||
|
||||
type HealthProps = {
|
||||
player: Player;
|
||||
onPlayerChange: (updatedPlayer: Player) => void;
|
||||
differenceKey: number;
|
||||
setDifferenceKey: (key: number) => void;
|
||||
rotation: Rotation;
|
||||
};
|
||||
|
||||
const Health = ({
|
||||
player,
|
||||
onPlayerChange,
|
||||
differenceKey,
|
||||
setDifferenceKey,
|
||||
rotation,
|
||||
}: HealthProps) => {
|
||||
const handleLifeChange = (updatedLifeTotal: number) => {
|
||||
const difference = updatedLifeTotal - player.lifeTotal;
|
||||
const updatedPlayer = {
|
||||
...player,
|
||||
lifeTotal: updatedLifeTotal,
|
||||
hasLost: false,
|
||||
};
|
||||
setRecentDifference(recentDifference + difference);
|
||||
onPlayerChange(updatedPlayer);
|
||||
setDifferenceKey(Date.now());
|
||||
};
|
||||
|
||||
const [recentDifference, setRecentDifference] = useState(0);
|
||||
const [showStartingPlayer, setShowStartingPlayer] = useState(
|
||||
localStorage.getItem('playing') === 'true'
|
||||
);
|
||||
const [fontSize, setFontSize] = useState(16);
|
||||
const textContainerRef = useRef<HTMLDivElement | null>(null);
|
||||
|
||||
useEffect(() => {
|
||||
const timer = setTimeout(() => {
|
||||
setRecentDifference(0);
|
||||
}, 3_000);
|
||||
|
||||
return () => clearTimeout(timer);
|
||||
}, [recentDifference]);
|
||||
|
||||
useEffect(() => {
|
||||
if (!showStartingPlayer) {
|
||||
const playingTimer = setTimeout(() => {
|
||||
localStorage.setItem('playing', 'true');
|
||||
setShowStartingPlayer(localStorage.getItem('playing') === 'true');
|
||||
}, 3_000);
|
||||
|
||||
return () => clearTimeout(playingTimer);
|
||||
}
|
||||
}, [showStartingPlayer]);
|
||||
|
||||
useEffect(() => {
|
||||
if (!textContainerRef.current) {
|
||||
return;
|
||||
}
|
||||
|
||||
const textContainer = textContainerRef.current;
|
||||
const resizeObserver = new ResizeObserver(() => {
|
||||
const calcFontSize = calculateFontSize(textContainer);
|
||||
setFontSize(calcFontSize);
|
||||
});
|
||||
|
||||
// Initially calculate font size
|
||||
const initialCalculation = () => {
|
||||
const calcFontSize = calculateFontSize(textContainer);
|
||||
setFontSize(calcFontSize);
|
||||
};
|
||||
initialCalculation();
|
||||
|
||||
resizeObserver.observe(textContainer);
|
||||
|
||||
return () => {
|
||||
// Cleanup: disconnect the ResizeObserver when the component unmounts.
|
||||
resizeObserver.disconnect();
|
||||
};
|
||||
// eslint-disable-next-line react-hooks/exhaustive-deps
|
||||
}, [textContainerRef]);
|
||||
|
||||
const calculateFontSize = (container: HTMLDivElement) => {
|
||||
const isSide =
|
||||
rotation === Rotation.SideFlipped || rotation === Rotation.Side;
|
||||
|
||||
const widthRatio = isSide ? container.clientHeight : container.clientWidth;
|
||||
|
||||
const heightRatio = isSide ? container.clientWidth : container.clientHeight;
|
||||
|
||||
const minRatio = Math.min(widthRatio, heightRatio);
|
||||
|
||||
const heightIsLarger = heightRatio > widthRatio;
|
||||
|
||||
const scaleFactor = heightIsLarger ? 0.8 : 1;
|
||||
|
||||
return minRatio * scaleFactor * 1;
|
||||
};
|
||||
|
||||
return (
|
||||
<LifeCountainer rotation={player.settings.rotation}>
|
||||
<LifeCounterButton
|
||||
lifeTotal={player.lifeTotal}
|
||||
setLifeTotal={handleLifeChange}
|
||||
rotation={player.settings.rotation}
|
||||
operation="subtract"
|
||||
increment={-1}
|
||||
/>
|
||||
<TextWrapper>
|
||||
<LifeCounterTextContainer
|
||||
rotation={player.settings.rotation}
|
||||
ref={textContainerRef}
|
||||
>
|
||||
<OutlinedText
|
||||
fontSize={`${fontSize}px`}
|
||||
strokeWidth={`${fontSize / 16}px`}
|
||||
rotation={player.settings.rotation}
|
||||
>
|
||||
{player.lifeTotal}
|
||||
</OutlinedText>
|
||||
{recentDifference !== 0 && (
|
||||
<RecentDifference key={differenceKey}>
|
||||
{recentDifference > 0 ? '+' : ''}
|
||||
{recentDifference}
|
||||
</RecentDifference>
|
||||
)}
|
||||
</LifeCounterTextContainer>
|
||||
</TextWrapper>
|
||||
<LifeCounterButton
|
||||
lifeTotal={player.lifeTotal}
|
||||
setLifeTotal={handleLifeChange}
|
||||
rotation={player.settings.rotation}
|
||||
operation="add"
|
||||
increment={1}
|
||||
/>
|
||||
</LifeCountainer>
|
||||
);
|
||||
};
|
||||
|
||||
export default Health;
|
||||
@@ -2,13 +2,19 @@ import { useEffect, useState } from 'react';
|
||||
import styled, { css, keyframes } from 'styled-components';
|
||||
import { theme } from '../../Data/theme';
|
||||
import { Player, Rotation } from '../../Types/Player';
|
||||
import LifeCounterButton from '../Buttons/LifeCounterButton';
|
||||
import { LoseGameButton } from '../Buttons/LoseButton';
|
||||
import SettingsButton from '../Buttons/SettingsButton';
|
||||
import CommanderDamageBar from '../Counters/CommanderDamageBar';
|
||||
import ExtraCountersBar from '../Counters/ExtraCountersBar';
|
||||
import { OutlinedText } from '../Misc/OutlinedText';
|
||||
import PlayerMenu from '../PlayerMenu/PlayerMenu';
|
||||
import Health from './Health';
|
||||
import { WakeLock } from '../../Types/WakeLock';
|
||||
|
||||
const Lmao = styled.div`
|
||||
position: absolute;
|
||||
width: 100%;
|
||||
height: 100%;
|
||||
`;
|
||||
|
||||
const LifeCounterContentWrapper = styled.div<{
|
||||
backgroundColor: string;
|
||||
@@ -59,29 +65,6 @@ const LifeCounterWrapper = styled.div<{
|
||||
}}
|
||||
`;
|
||||
|
||||
const LifeCountainer = styled.div<{
|
||||
rotation: Rotation;
|
||||
}>`
|
||||
display: flex;
|
||||
flex-direction: row;
|
||||
flex-grow: 1;
|
||||
width: 100%;
|
||||
height: 100%;
|
||||
justify-content: space-between;
|
||||
align-items: center;
|
||||
|
||||
${(props) => {
|
||||
if (
|
||||
props.rotation === Rotation.SideFlipped ||
|
||||
props.rotation === Rotation.Side
|
||||
) {
|
||||
return css`
|
||||
flex-direction: column-reverse;
|
||||
`;
|
||||
}
|
||||
}}
|
||||
`;
|
||||
|
||||
const PlayerNoticeWrapper = styled.div<{
|
||||
rotation: Rotation;
|
||||
backgroundColor: string;
|
||||
@@ -128,31 +111,6 @@ const DynamicText = styled.div<{ rotation: Rotation }>`
|
||||
}}
|
||||
`;
|
||||
|
||||
const LifeCounterTextContainer = styled.p<{
|
||||
rotation: Rotation;
|
||||
}>`
|
||||
margin: 0;
|
||||
padding: 0;
|
||||
pointer-events: none;
|
||||
-webkit-touch-callout: none;
|
||||
-webkit-tap-highlight-color: transparent;
|
||||
user-select: none;
|
||||
-moz-user-select: -moz-none;
|
||||
-webkit-user-select: none;
|
||||
-ms-user-select: none;
|
||||
${(props) => {
|
||||
if (
|
||||
props.rotation === Rotation.SideFlipped ||
|
||||
props.rotation === Rotation.Side
|
||||
) {
|
||||
return css`
|
||||
rotate: 270deg;
|
||||
margin-right: 25%;
|
||||
`;
|
||||
}
|
||||
}}
|
||||
`;
|
||||
|
||||
const fadeOut = keyframes`
|
||||
0% {
|
||||
opacity: 1;
|
||||
@@ -180,14 +138,6 @@ export const RecentDifference = styled.span`
|
||||
animation: ${fadeOut} 3s 1s ease-out forwards;
|
||||
`;
|
||||
|
||||
interface LifeCounterProps {
|
||||
backgroundColor: string;
|
||||
player: Player;
|
||||
opponents: Player[];
|
||||
onPlayerChange: (updatedPlayer: Player) => void;
|
||||
resetCurrentGame: () => void;
|
||||
}
|
||||
|
||||
const hasCommanderDamageReached21 = (player: Player) => {
|
||||
const commanderDamageTotals = player.commanderDamage.map(
|
||||
(commanderDamage) => commanderDamage.damageTotal
|
||||
@@ -215,12 +165,22 @@ const playerCanLose = (player: Player) => {
|
||||
);
|
||||
};
|
||||
|
||||
type LifeCounterProps = {
|
||||
backgroundColor: string;
|
||||
player: Player;
|
||||
opponents: Player[];
|
||||
onPlayerChange: (updatedPlayer: Player) => void;
|
||||
resetCurrentGame: () => void;
|
||||
wakeLock: WakeLock;
|
||||
};
|
||||
|
||||
const LifeCounter = ({
|
||||
backgroundColor,
|
||||
player,
|
||||
opponents,
|
||||
onPlayerChange,
|
||||
resetCurrentGame,
|
||||
wakeLock,
|
||||
}: LifeCounterProps) => {
|
||||
const handleLifeChange = (updatedLifeTotal: number) => {
|
||||
const difference = updatedLifeTotal - player.lifeTotal;
|
||||
@@ -231,7 +191,7 @@ const LifeCounter = ({
|
||||
};
|
||||
setRecentDifference(recentDifference + difference);
|
||||
onPlayerChange(updatedPlayer);
|
||||
setKey(Date.now());
|
||||
setDifferenceKey(Date.now());
|
||||
};
|
||||
|
||||
const toggleGameLost = () => {
|
||||
@@ -244,7 +204,7 @@ const LifeCounter = ({
|
||||
const [showStartingPlayer, setShowStartingPlayer] = useState(
|
||||
localStorage.getItem('playing') === 'true'
|
||||
);
|
||||
const [key, setKey] = useState(Date.now());
|
||||
const [differenceKey, setDifferenceKey] = useState(Date.now());
|
||||
|
||||
useEffect(() => {
|
||||
const timer = setTimeout(() => {
|
||||
@@ -268,26 +228,9 @@ const LifeCounter = ({
|
||||
player.settings.rotation === Rotation.SideFlipped ||
|
||||
player.settings.rotation === Rotation.Side;
|
||||
|
||||
const size =
|
||||
player.settings.rotation === Rotation.SideFlipped ||
|
||||
player.settings.rotation === Rotation.Side
|
||||
? 15
|
||||
: 30;
|
||||
|
||||
const fontSize =
|
||||
player.settings.rotation === Rotation.SideFlipped ||
|
||||
player.settings.rotation === Rotation.Side
|
||||
? `${size}vmax`
|
||||
: `${size}vmin`;
|
||||
|
||||
const strokeWidth =
|
||||
player.settings.rotation === Rotation.SideFlipped ||
|
||||
player.settings.rotation === Rotation.Side
|
||||
? `${size / 20}vmax`
|
||||
: `${size / 20}vmin`;
|
||||
|
||||
return (
|
||||
<LifeCounterContentWrapper backgroundColor={backgroundColor}>
|
||||
<Lmao>
|
||||
<LifeCounterWrapper rotation={player.settings.rotation}>
|
||||
{player.isStartingPlayer && !showStartingPlayer && (
|
||||
<PlayerNoticeWrapper
|
||||
@@ -324,36 +267,16 @@ const LifeCounter = ({
|
||||
onClick={toggleGameLost}
|
||||
/>
|
||||
)}
|
||||
<LifeCountainer rotation={player.settings.rotation}>
|
||||
<LifeCounterButton
|
||||
lifeTotal={player.lifeTotal}
|
||||
setLifeTotal={handleLifeChange}
|
||||
<Health
|
||||
player={player}
|
||||
onPlayerChange={onPlayerChange}
|
||||
differenceKey={differenceKey}
|
||||
setDifferenceKey={setDifferenceKey}
|
||||
rotation={player.settings.rotation}
|
||||
operation="subtract"
|
||||
increment={-1}
|
||||
/>
|
||||
<LifeCounterTextContainer rotation={player.settings.rotation}>
|
||||
<OutlinedText fontSize={fontSize} strokeWidth={strokeWidth}>
|
||||
{player.lifeTotal}
|
||||
</OutlinedText>
|
||||
{recentDifference !== 0 && (
|
||||
<RecentDifference key={key}>
|
||||
{recentDifference > 0 ? '+' : ''}
|
||||
{recentDifference}
|
||||
</RecentDifference>
|
||||
)}
|
||||
</LifeCounterTextContainer>
|
||||
<LifeCounterButton
|
||||
lifeTotal={player.lifeTotal}
|
||||
setLifeTotal={handleLifeChange}
|
||||
rotation={player.settings.rotation}
|
||||
operation="add"
|
||||
increment={1}
|
||||
/>
|
||||
</LifeCountainer>
|
||||
<ExtraCountersBar player={player} onPlayerChange={onPlayerChange} />
|
||||
</LifeCounterWrapper>
|
||||
|
||||
</Lmao>
|
||||
{showPlayerMenu && (
|
||||
<PlayerMenu
|
||||
player={player}
|
||||
@@ -361,6 +284,7 @@ const LifeCounter = ({
|
||||
onPlayerChange={onPlayerChange}
|
||||
setShowPlayerMenu={setShowPlayerMenu}
|
||||
resetCurrentGame={resetCurrentGame}
|
||||
wakeLock={wakeLock}
|
||||
/>
|
||||
)}
|
||||
</LifeCounterContentWrapper>
|
||||
|
||||
@@ -1,5 +1,15 @@
|
||||
import styled from 'styled-components';
|
||||
import styled, { css } from 'styled-components';
|
||||
import { theme } from '../../Data/theme';
|
||||
import { Rotation } from '../../Types/Player';
|
||||
|
||||
const Container = styled.div`
|
||||
display: flex;
|
||||
position: relative;
|
||||
width: 100%;
|
||||
height: 100%;
|
||||
align-items: center;
|
||||
justify-content: center;
|
||||
`;
|
||||
|
||||
const CenteredText = styled.div<{
|
||||
strokeWidth?: string;
|
||||
@@ -7,11 +17,9 @@ const CenteredText = styled.div<{
|
||||
fillColor?: string;
|
||||
fontSize?: string;
|
||||
fontWeight?: string;
|
||||
rotation?: Rotation;
|
||||
}>`
|
||||
position: absolute;
|
||||
top: 50%;
|
||||
left: 50%;
|
||||
transform: translate(-50%, -50%);
|
||||
font-weight: ${(props) => props.fontWeight || ''};
|
||||
font-variant-numeric: tabular-nums;
|
||||
user-select: none;
|
||||
@@ -26,6 +34,17 @@ const CenteredText = styled.div<{
|
||||
-webkit-text-stroke: ${(props) => props.strokeWidth || '1vmin'} ${(props) => props.strokeColor || theme.palette.common.white};
|
||||
-webkit-text-fill-color: ${(props) =>
|
||||
props.fillColor || theme.palette.common.black};
|
||||
|
||||
${(props) => {
|
||||
if (
|
||||
props.rotation === Rotation.SideFlipped ||
|
||||
props.rotation === Rotation.Side
|
||||
) {
|
||||
return css`
|
||||
rotate: 270deg;
|
||||
`;
|
||||
}
|
||||
}}
|
||||
`;
|
||||
|
||||
const CenteredTextOutline = styled.span`
|
||||
@@ -42,6 +61,7 @@ type OutlinedTextProps = {
|
||||
strokeWidth?: string;
|
||||
strokeColor?: string;
|
||||
fillColor?: string;
|
||||
rotation?: Rotation;
|
||||
};
|
||||
|
||||
export const OutlinedText: React.FC<OutlinedTextProps> = ({
|
||||
@@ -51,17 +71,21 @@ export const OutlinedText: React.FC<OutlinedTextProps> = ({
|
||||
strokeWidth,
|
||||
strokeColor,
|
||||
fillColor,
|
||||
rotation,
|
||||
}) => {
|
||||
return (
|
||||
<Container>
|
||||
<CenteredText
|
||||
fontSize={fontSize}
|
||||
fontWeight={fontWeight}
|
||||
strokeWidth={strokeWidth}
|
||||
strokeColor={strokeColor}
|
||||
fillColor={fillColor}
|
||||
rotation={rotation}
|
||||
>
|
||||
{children}
|
||||
<CenteredTextOutline aria-hidden>{children}</CenteredTextOutline>
|
||||
</CenteredText>
|
||||
</Container>
|
||||
);
|
||||
};
|
||||
|
||||
Reference in New Issue
Block a user