Make action cooldown a dial rather than a progress bar, and make it always visible.

This commit is contained in:
Ryan Lanny Jenkins 2025-05-18 23:01:02 -05:00
parent 00db07e637
commit 8035aa92d4
2 changed files with 63 additions and 13 deletions

View file

@ -4,19 +4,62 @@ import { styled } from '@linaria/react'
import { useGameStore } from '../store/useGameStore' import { useGameStore } from '../store/useGameStore'
const CooldownContainer = styled.div` const CooldownContainer = styled.div`
position: relative; position: fixed;
height: 1rem; top: 1rem;
width: 100%; left: 1rem;
background-color: #e5e7eb; width: 48px;
overflow: hidden; height: 48px;
display: flex;
align-items: center;
justify-content: center;
` `
const ProgressBar = styled.div<{ progress: string }>` const DialSVG = styled.svg`
width: 100%;
height: 100%; height: 100%;
background-color: #3b82f6;
width: ${(props) => props.progress};
` `
const DialBackground = styled.circle`
fill: #e5e7eb;
`
const DialProgress = styled.path`
fill: #3b82f6;
`
const calculatePieWedge = (progress: number, size: number) => {
// Convert progress to go counter-clockwise from top
const adjustedProgress = 100 - progress
const center = size / 2
const radius = size / 2 - 1
const angle = (adjustedProgress / 100) * 360
// Always start from top (90 degrees in SVG coordinates)
const startAngle = 90
const endAngle = startAngle + angle
// Convert angles to radians
const startAngleRad = (startAngle * Math.PI) / 180
const endAngleRad = (endAngle * Math.PI) / 180
// Calculate points
const startX = center + radius * Math.cos(startAngleRad)
const startY = center - radius * Math.sin(startAngleRad)
const endX = center + radius * Math.cos(endAngleRad)
const endY = center - radius * Math.sin(endAngleRad)
// Create the arc flag
const largeArcFlag = angle <= 180 ? '0' : '1'
// Create the SVG path - moving counter-clockwise
return `
M ${center},${center}
L ${startX},${startY}
A ${radius} ${radius} 0 ${largeArcFlag} 0 ${endX} ${endY}
L ${center},${center}
`.trim()
}
export const ActionCooldown = () => { export const ActionCooldown = () => {
const { actionCooldown, setActionCooldown } = useGameStore() const { actionCooldown, setActionCooldown } = useGameStore()
const [progress, setProgress] = useState(0) const [progress, setProgress] = useState(0)
@ -51,9 +94,17 @@ export const ActionCooldown = () => {
} }
}, [actionCooldown, setActionCooldown]) }, [actionCooldown, setActionCooldown])
// Don't render if there's no active cooldown
if (actionCooldown <= 0) {
return null
}
return ( return (
<CooldownContainer> <CooldownContainer>
<ProgressBar progress={`${progress}%`} /> <DialSVG viewBox="0 0 32 32">
<DialBackground cx="16" cy="16" r="15" />
<DialProgress d={calculatePieWedge(progress, 32)} />
</DialSVG>
</CooldownContainer> </CooldownContainer>
) )
} }

View file

@ -222,9 +222,7 @@ const PlotInfoModal: React.FC<PlotInfoModalProps> = ({ plot, onClose }) => {
</div> </div>
<div style={plotInfoItemStyle}> <div style={plotInfoItemStyle}>
<span>Intended Crop:</span> <span>Intended Crop:</span>
<span> <span>{plot.intended ? CROPS[plot.intended].name : 'None'}</span>
{plot.intended ? CROPS[plot.intended].name : 'None'}
</span>
</div> </div>
<div style={plotInfoItemStyle}> <div style={plotInfoItemStyle}>
<span>Water Level:</span> <span>Water Level:</span>
@ -239,7 +237,8 @@ const PlotInfoModal: React.FC<PlotInfoModalProps> = ({ plot, onClose }) => {
<span>Growth Progress:</span> <span>Growth Progress:</span>
<span> <span>
{formatPercentage( {formatPercentage(
plot.current.progress / CROPS[plot.current.cropId].growthTicks, plot.current.progress /
CROPS[plot.current.cropId].growthTicks,
)} )}
</span> </span>
</div> </div>