feat: life bar
This commit is contained in:
parent
e8ae1ef73f
commit
2eebb77ddf
56
packages/app/src/components/app/play/ui/health/index.jsx
Normal file
56
packages/app/src/components/app/play/ui/health/index.jsx
Normal file
|
@ -0,0 +1,56 @@
|
|||
import {usePropertyChange} from '@avocado/react';
|
||||
import {PropTypes, React} from '@flecks/react';
|
||||
|
||||
import styles from './index.module.scss';
|
||||
|
||||
function Health({selfEntity}) {
|
||||
const life = usePropertyChange(selfEntity, 'life');
|
||||
const maxLife = usePropertyChange(selfEntity, 'maxLife');
|
||||
const filled = life / maxLife;
|
||||
let color = 'white';
|
||||
if (filled < 0.25) {
|
||||
color = `rgb(${255}, ${(255 * 4) * filled}, 0)`;
|
||||
}
|
||||
else if (filled < 0.5) {
|
||||
color = `rgb(${255}, ${255}, ${(255 * 4) * (filled - 0.25)})`;
|
||||
}
|
||||
const duration = filled < 0.25 ? Math.max(0.5, (filled / 0.125)) : 0;
|
||||
return (
|
||||
<div
|
||||
className={styles.health}
|
||||
style={{
|
||||
'--filled': filled,
|
||||
}}
|
||||
>
|
||||
<p className={styles.text}>
|
||||
<span
|
||||
className={styles.life}
|
||||
style={{
|
||||
animationDuration: `${duration}s`,
|
||||
color,
|
||||
}}
|
||||
>
|
||||
{life}
|
||||
</span>
|
||||
</p>
|
||||
<div className={styles.meterWrapper}>
|
||||
<div className={styles.meter}>
|
||||
<div className={styles.fill} />
|
||||
</div>
|
||||
</div>
|
||||
<p className={styles.text}>
|
||||
<span className={styles.maxLife}>{maxLife}</span>
|
||||
</p>
|
||||
</div>
|
||||
);
|
||||
}
|
||||
|
||||
Health.defaultProps = {};
|
||||
|
||||
Health.displayName = 'Health';
|
||||
|
||||
Health.propTypes = {
|
||||
selfEntity: PropTypes.shape({}).isRequired,
|
||||
};
|
||||
|
||||
export default Health;
|
|
@ -0,0 +1,83 @@
|
|||
@import '../../../../../scss/graphics.scss';
|
||||
|
||||
.health {
|
||||
--border-width: 3px;
|
||||
--height: 300px;
|
||||
--width: 30px;
|
||||
|
||||
align-items: center;
|
||||
display: flex;
|
||||
font-family: joystix;
|
||||
flex-direction: column;
|
||||
opacity: 0.8;
|
||||
padding: 20px;
|
||||
position: absolute;
|
||||
left: 0;
|
||||
top: 0;
|
||||
}
|
||||
|
||||
.health span {
|
||||
display: block;
|
||||
text-align: center;
|
||||
}
|
||||
|
||||
.life {
|
||||
animation: lifeFlicker infinite;
|
||||
animation-duration: 500ms;
|
||||
font-size: 2em;
|
||||
@include shadow-text(2px, black, 0px);
|
||||
}
|
||||
|
||||
.maxLife {
|
||||
@include shadow-text(1px, black, 0px);
|
||||
}
|
||||
|
||||
@keyframes lifeFlicker {
|
||||
0% {
|
||||
opacity: 1;
|
||||
}
|
||||
30% {
|
||||
opacity: 1;
|
||||
}
|
||||
45% {
|
||||
opacity: 0.5;
|
||||
}
|
||||
50% {
|
||||
opacity: 0;
|
||||
}
|
||||
55% {
|
||||
opacity: 0.5;
|
||||
}
|
||||
70% {
|
||||
opacity: 1;
|
||||
}
|
||||
}
|
||||
|
||||
.meterWrapper {
|
||||
border-radius: 20px;
|
||||
border: var(--border-width) solid black;
|
||||
height: var(--height);
|
||||
overflow: hidden;
|
||||
position: relative;
|
||||
width: var(--width);
|
||||
}
|
||||
|
||||
.meter {
|
||||
bottom: 0;
|
||||
height: calc(var(--height) * var(--filled) - (2 * var(--border-width)));
|
||||
overflow: hidden;
|
||||
position: absolute;
|
||||
width: 100%;
|
||||
}
|
||||
|
||||
.fill {
|
||||
background-image: linear-gradient(to top, red 0%, yellow 50%, green 100%);
|
||||
box-shadow: inset 0 0 calc(0.66 * var(--width)) rgba(0, 0, 0, 0.8);
|
||||
height: calc(var(--height) - (2 * var(--border-width)));
|
||||
position: relative;
|
||||
top: calc(-1 * var(--height) * (1 - var(--filled)));
|
||||
}
|
||||
|
||||
.text {
|
||||
margin-bottom: 10px;
|
||||
}
|
|
@ -12,6 +12,7 @@ import {
|
|||
useRoom,
|
||||
useSelfEntity,
|
||||
} from '../../../../hooks';
|
||||
import Health from './health';
|
||||
import Hotbar from './hotbar';
|
||||
import styles from './index.module.scss';
|
||||
|
||||
|
@ -47,7 +48,12 @@ const PlayUi = () => {
|
|||
ref={ref}
|
||||
room={room}
|
||||
/>
|
||||
{selfEntity && <Hotbar selfEntity={selfEntity} />}
|
||||
{selfEntity && (
|
||||
<>
|
||||
<Health selfEntity={selfEntity} />
|
||||
<Hotbar selfEntity={selfEntity} />
|
||||
</>
|
||||
)}
|
||||
</div>
|
||||
);
|
||||
};
|
||||
|
|
|
@ -6,3 +6,12 @@
|
|||
$size -#{$size} $radius $color
|
||||
;
|
||||
}
|
||||
|
||||
@mixin shadow-text($size, $color, $radius: $size) {
|
||||
text-shadow:
|
||||
-#{$size} -#{$size} $radius $color,
|
||||
$size $size $radius $color,
|
||||
-#{$size} $size $radius $color,
|
||||
$size -#{$size} $radius $color
|
||||
;
|
||||
}
|
||||
|
|
Loading…
Reference in New Issue
Block a user