Add initial character creation screen
Created the first version of the character creation feature, including the base layout and starting UI elements for customizing a character.
This commit is contained in:
66
components/character/tinted-sprite-icon.tsx
Normal file
66
components/character/tinted-sprite-icon.tsx
Normal file
@@ -0,0 +1,66 @@
|
||||
"use client";
|
||||
|
||||
import { useEffect, useRef } from "react";
|
||||
|
||||
import {
|
||||
drawTintedSprite,
|
||||
getCachedImage,
|
||||
hslToRgb,
|
||||
type HSL,
|
||||
} from "@/lib/character/color-utils";
|
||||
import { cn } from "@/lib/utils";
|
||||
|
||||
type TintedSpriteIconProps = {
|
||||
src: string;
|
||||
color: HSL;
|
||||
size?: number;
|
||||
className?: string;
|
||||
};
|
||||
|
||||
export function TintedSpriteIcon({
|
||||
src,
|
||||
color,
|
||||
size = 40,
|
||||
className,
|
||||
}: TintedSpriteIconProps) {
|
||||
const canvasRef = useRef<HTMLCanvasElement>(null);
|
||||
|
||||
useEffect(() => {
|
||||
let cancelled = false;
|
||||
|
||||
async function render() {
|
||||
const canvas = canvasRef.current;
|
||||
if (!canvas) return;
|
||||
|
||||
const ctx = canvas.getContext("2d", { willReadFrequently: true });
|
||||
if (!ctx) return;
|
||||
|
||||
const image = await getCachedImage(src);
|
||||
if (cancelled) return;
|
||||
|
||||
canvas.width = image.width;
|
||||
canvas.height = image.height;
|
||||
ctx.clearRect(0, 0, image.width, image.height);
|
||||
drawTintedSprite(ctx, image, hslToRgb(color.h, color.s, color.l));
|
||||
}
|
||||
|
||||
render();
|
||||
|
||||
return () => {
|
||||
cancelled = true;
|
||||
};
|
||||
}, [src, color]);
|
||||
|
||||
return (
|
||||
<canvas
|
||||
ref={canvasRef}
|
||||
aria-hidden
|
||||
className={cn("block max-h-full max-w-full", className)}
|
||||
style={{
|
||||
imageRendering: "pixelated",
|
||||
width: size,
|
||||
height: size,
|
||||
}}
|
||||
/>
|
||||
);
|
||||
}
|
||||
Reference in New Issue
Block a user