Skip to content

Commit

Permalink
feat(ui): added EntityPreview component, updated EpisodeListItem
Browse files Browse the repository at this point in the history
…and `LevelListItem`
  • Loading branch information
wialy committed Mar 25, 2024
1 parent 0531e7e commit 1034991
Show file tree
Hide file tree
Showing 7 changed files with 188 additions and 63 deletions.
Original file line number Diff line number Diff line change
@@ -0,0 +1,88 @@
.container {
display: flex;
width: 1.25rem;
height: 1.25rem;
flex-shrink: 0;
border-radius: 0.25rem;
justify-content: center;
align-items: center;
text-align: start;
appearance: none;
color: white;
}

.dice0 {
background-color: var(--color-orange);
}

.dice1 {
background-color: var(--color-yellow);
}

.dice2 {
background-color: var(--color-green);
}

.dice3 {
background-color: var(--color-teal);
}

.dice4 {
background-color: var(--color-blue);
}

.dice5 {
background-color: var(--color-purple);
}

.dice6 {
background-color: var(--color-red);
}

.movable {
background-color: var(--color-white);
}

.floor {
background-color: rgba(255, 255, 255, 0.15);
}

.director,
.target {
border: 1px solid rgba(255, 255, 255, 0.25);
}

.target0 {
border: 1px solid var(--color-orange);
color: var(--color-orange);
}

.target1 {
border: 1px solid var(--color-yellow);
color: var(--color-yellow);
}

.target2 {
border: 1px solid var(--color-green);
color: var(--color-green);
}

.target3 {
border: 1px solid var(--color-teal);
color: var(--color-teal);
}

.target4 {
border: 1px solid var(--color-blue);
color: var(--color-blue);
}

.target5 {
border: 1px solid var(--color-purple);
color: var(--color-purple);
}

.target6 {
border: 1px solid var(--color-red);
color: var(--color-red);
}
55 changes: 55 additions & 0 deletions src/features/ui/components/entity-preview/entity-preview.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,55 @@
import clsx from 'clsx';

import {
Entity,
isDice,
isFloor,
isMovable,
} from '../../../engine/types/entities';
import { getArrowSymbol } from '../../utils/get-arrow-symbol';
import $$ from './entity-preview.module.css';

export const EntityPreview = ({ entity }: { entity?: Entity }) => {
if (!entity) {
return <div className={clsx($$.container)} />;
}

if (isDice(entity)) {
const { value } = entity;

return (
<div className={clsx($$.container, $$[`dice${value}`])}>{2 ** value}</div>
);
}

if (isMovable(entity)) {
return <div className={clsx($$.container, $$.movable)} />;
}

if (isFloor(entity)) {
if (entity.target !== undefined) {
return (
<div
className={clsx(
$$.container,
$$.floor,
$$.target,
$$[`target${entity.target}`],
)}
>
{2 ** entity.target}
</div>
);
} else if (entity.direction !== undefined) {
return (
<div className={clsx($$.container, $$.floor, $$.director)}>
{getArrowSymbol(entity.direction)}
</div>
);
}

return <div className={clsx($$.container, $$.floor)} />;
}

return <div className={clsx($$.container)}>X</div>;
};
2 changes: 0 additions & 2 deletions src/features/ui/components/entity-view/entity-view.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -153,8 +153,6 @@ export const EntityView = ({
boxShadow,
fontSize: TILE_SIZE / 2.5,
height: size,
perspective: '30px',
perspectiveOrigin: '50% 50%',
transform: `translate(${-size / 2}px, ${-size / 2}px) scale(${scaleX}, ${scaleY})`,
transitionDuration: `${Number(MOVE_DURATION * 3)}ms`,
width: size,
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -10,6 +10,7 @@
cursor: pointer;
gap: 1.5rem;
color: black;
font-size: 0.75rem;
}

.name {
Expand All @@ -33,8 +34,8 @@
display: flex;
align-items: center;
background-color: var(--color-navy);
height: 3rem;
justify-content: center;
padding-left: 1.75rem;
border-radius: 0.5rem;
padding: 0.5rem;
gap: 2px;
border-radius: 0.75rem;
}
41 changes: 10 additions & 31 deletions src/features/ui/components/episode-list-item/episode-list-item.tsx
Original file line number Diff line number Diff line change
@@ -1,18 +1,14 @@
import { ID_SYMBOLS } from '../../../editor/constants';
import { useEpisodeLevels } from '../../../editor/hooks/use-episode-levels';
import { EpisodeRecord } from '../../../editor/types';
import { getParsedLevelRecord } from '../../../editor/utils/get-parsed-level-record';
import { getSymbolEntity } from '../../../editor/utils/get-symbol-entity';
import { Entity } from '../../../engine/types/entities';
import { useGameState } from '../../../game/hooks/use-game-state';
import { useHighscores } from '../../../game/hooks/use-highscores';
import { TILE_SIZE } from '../../constants';
import { EntityView } from '../entity-view';
import { EntityPreview } from '../entity-preview/entity-preview';
import { Icon } from '../icon';
import $$ from './episode-list-item.module.css';

const SCALE = 0.3;

export const EpisodeListItem = ({ name, symbols }: EpisodeRecord) => {
const { setEpisode, setScreen } = useGameState();
const { highscores } = useHighscores();
Expand Down Expand Up @@ -40,14 +36,9 @@ export const EpisodeListItem = ({ name, symbols }: EpisodeRecord) => {
}
}

const entities = [...symbols]
.filter((symbol) => ![ID_SYMBOLS.floor].includes(symbol))
.map((symbol) => getSymbolEntity(symbol))
.filter(Boolean)
.map((entity, index) => ({
...entity,
position: { x: index, y: 0 },
})) as Entity[];
const entities = [...symbols].map((symbol) =>
getSymbolEntity(symbol),
) as Entity[];

return (
<button
Expand All @@ -60,24 +51,12 @@ export const EpisodeListItem = ({ name, symbols }: EpisodeRecord) => {
<div className={$$.name}>{name}</div>

<div className={$$.symbols}>
<div
style={{
position: 'relative',
width: entities.length * TILE_SIZE * SCALE,
}}
>
{entities.map((entity) => {
if (!entity) return null;

return (
<EntityView
key={entity.id}
entity={entity}
scale={SCALE}
/>
);
})}
</div>
{entities.map((entity, index) => (
<EntityPreview
key={index}
entity={entity}
/>
))}
</div>

<div className={$$.description}>
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -57,14 +57,23 @@
}

.previewContainer {
pointer-events: none;
align-items: center;
background-color: var(--color-navy);
display: flex;
flex-direction: column;
justify-content: center;
padding: 1rem;
pointer-events: none;
width: 100%;
height: 150px;
gap: 2px;
}

.previewRow {
display: flex;
flex-direction: row;
gap: 2px;
}

.previewContainer.locked {
Expand Down
49 changes: 22 additions & 27 deletions src/features/ui/components/level-list-item/level-list-item.tsx
Original file line number Diff line number Diff line change
@@ -1,14 +1,13 @@
import clsx from 'clsx';
import { memo, useEffect, useRef } from 'react';

import { ID_SYMBOLS } from '../../../editor/constants';
import { LevelRecord } from '../../../editor/types';
import { getIdEntities } from '../../../editor/utils/get-id-entities';
import { getBounds } from '../../../engine/utils/get-bounds';
import { getSymbolEntity } from '../../../editor/utils/get-symbol-entity';
import { MAX_MOVES_MULTIPLIER } from '../../../game/constants';
import { useGameState } from '../../../game/hooks/use-game-state';
import { Highscore } from '../../../game/types';
import { TILE_SIZE } from '../../constants';
import { EntityView } from '../entity-view';
import { EntityPreview } from '../entity-preview/entity-preview';
import { Icon } from '../icon';
import $$ from './level-list-item.module.css';

Expand Down Expand Up @@ -90,34 +89,30 @@ export const LevelListItem = ({
);
};

const SCALE = 0.2;

const Preview = memo(({ id, isLocked }: { id: string; isLocked?: boolean }) => {
const entities = getIdEntities(id);
const { bottomRight, topLeft } = getBounds({ entities });
const width = bottomRight.x - topLeft.x;
const height = bottomRight.y - topLeft.y;
const rows = id.split(ID_SYMBOLS.delimiter).map((row) => [...row]);

return (
<div className={clsx($$.previewContainer, { [$$.locked]: isLocked })}>
{Boolean(isLocked) && <div className={$$.lock}>🔒</div>}
{!isLocked && (
<pre
style={{
height: height * TILE_SIZE * SCALE,
position: 'relative',
width: width * TILE_SIZE * SCALE,
}}
>
{entities.map((entity) => (
<EntityView
key={entity.id}
entity={entity}
scale={SCALE}
/>
))}
</pre>
)}
{!isLocked &&
rows.map((row, y) => (
<div
key={y}
className={$$.previewRow}
>
{row.map((symbol, x) => {
const entity = getSymbolEntity(symbol);

return (
<EntityPreview
key={x}
entity={entity}
/>
);
})}
</div>
))}
</div>
);
});
Expand Down

0 comments on commit 1034991

Please sign in to comment.