fix: make textures solid color at smaller scales
This commit is contained in:
parent
ab3d36257e
commit
2772577a7b
3 changed files with 54 additions and 13 deletions
|
|
@ -4,12 +4,14 @@ import * as PIXI from "pixi.js";
|
||||||
import { useApp } from "@pixi/react";
|
import { useApp } from "@pixi/react";
|
||||||
import { CompositeTilemap, settings } from "@pixi/tilemap";
|
import { CompositeTilemap, settings } from "@pixi/tilemap";
|
||||||
|
|
||||||
import blocksData from "@/data/blocks/programmer-art/data.json";
|
import _blockData from "@/data/blocks/programmer-art/data.json";
|
||||||
|
const blockData: BlockData = _blockData;
|
||||||
|
|
||||||
interface Props {
|
interface Props {
|
||||||
blocks: Block[];
|
blocks: Block[];
|
||||||
setBlocks: React.Dispatch<React.SetStateAction<Block[]>>;
|
setBlocks: React.Dispatch<React.SetStateAction<Block[]>>;
|
||||||
textures: Record<string, PIXI.Texture>;
|
textures: Record<string, PIXI.Texture>;
|
||||||
|
solidTextures: Record<string, PIXI.Texture>;
|
||||||
image: HTMLImageElement | undefined;
|
image: HTMLImageElement | undefined;
|
||||||
imageDimensions: Dimension;
|
imageDimensions: Dimension;
|
||||||
coords: Position;
|
coords: Position;
|
||||||
|
|
@ -20,7 +22,7 @@ interface Props {
|
||||||
// Lifts 16,000 tiles limit
|
// Lifts 16,000 tiles limit
|
||||||
settings.use32bitIndex = true;
|
settings.use32bitIndex = true;
|
||||||
|
|
||||||
function Blocks({ blocks, setBlocks, textures, image, imageDimensions, coords, scale, setLoading }: Props) {
|
function Blocks({ blocks, setBlocks, textures, solidTextures, image, imageDimensions, coords, scale, setLoading }: Props) {
|
||||||
const app = useApp();
|
const app = useApp();
|
||||||
const [missingTexture, setMissingTexture] = useState<PIXI.Texture>();
|
const [missingTexture, setMissingTexture] = useState<PIXI.Texture>();
|
||||||
|
|
||||||
|
|
@ -31,9 +33,16 @@ function Blocks({ blocks, setBlocks, textures, image, imageDimensions, coords, s
|
||||||
const tilemap = tilemapRef.current;
|
const tilemap = tilemapRef.current;
|
||||||
tilemap.clear();
|
tilemap.clear();
|
||||||
|
|
||||||
|
// Tile solid colors at smaller scales
|
||||||
|
if (scale >= 0.5) {
|
||||||
blocks.forEach((block) => {
|
blocks.forEach((block) => {
|
||||||
tilemap.tile(textures[`${block.name}.png`] ?? missingTexture, block.x * 16, block.y * 16);
|
tilemap.tile(textures[`${block.name}.png`] ?? missingTexture, block.x * 16, block.y * 16);
|
||||||
});
|
});
|
||||||
|
} else {
|
||||||
|
blocks.forEach((block) => {
|
||||||
|
tilemap.tile(solidTextures[`${block.name}`] ?? missingTexture, block.x * 16, block.y * 16);
|
||||||
|
});
|
||||||
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
useEffect(() => {
|
useEffect(() => {
|
||||||
|
|
@ -69,7 +78,7 @@ function Blocks({ blocks, setBlocks, textures, image, imageDimensions, coords, s
|
||||||
let closestBlock = "";
|
let closestBlock = "";
|
||||||
let closestDistance = Infinity;
|
let closestDistance = Infinity;
|
||||||
|
|
||||||
Object.entries(blocksData).forEach(([block, data]) => {
|
Object.entries(blockData).forEach(([block, data]) => {
|
||||||
const distance = Math.sqrt(
|
const distance = Math.sqrt(
|
||||||
Math.pow(r - data.color[0], 2) + Math.pow(g - data.color[1], 2) + Math.pow(b - data.color[2], 2) + Math.pow(a - data.color[3], 3)
|
Math.pow(r - data.color[0], 2) + Math.pow(g - data.color[1], 2) + Math.pow(b - data.color[2], 2) + Math.pow(a - data.color[3], 3)
|
||||||
);
|
);
|
||||||
|
|
|
||||||
|
|
@ -28,7 +28,7 @@ function Canvas() {
|
||||||
const { image, imageDimensions } = useContext(ImageContext);
|
const { image, imageDimensions } = useContext(ImageContext);
|
||||||
const { setLoading } = useContext(LoadingContext);
|
const { setLoading } = useContext(LoadingContext);
|
||||||
const { settings } = useContext(SettingsContext);
|
const { settings } = useContext(SettingsContext);
|
||||||
const textures = useContext(TexturesContext);
|
const { textures, solidTextures } = useContext(TexturesContext);
|
||||||
const { tool, selectedBlock, cssCursor, setTool, setCssCursor } = useContext(ToolContext);
|
const { tool, selectedBlock, cssCursor, setTool, setCssCursor } = useContext(ToolContext);
|
||||||
|
|
||||||
const stageContainerRef = useRef<HTMLDivElement>(null);
|
const stageContainerRef = useRef<HTMLDivElement>(null);
|
||||||
|
|
@ -250,6 +250,7 @@ function Canvas() {
|
||||||
blocks={visibleBlocks}
|
blocks={visibleBlocks}
|
||||||
setBlocks={setBlocks}
|
setBlocks={setBlocks}
|
||||||
textures={textures}
|
textures={textures}
|
||||||
|
solidTextures={solidTextures}
|
||||||
image={image}
|
image={image}
|
||||||
imageDimensions={imageDimensions}
|
imageDimensions={imageDimensions}
|
||||||
coords={coords}
|
coords={coords}
|
||||||
|
|
|
||||||
|
|
@ -1,27 +1,58 @@
|
||||||
import { createContext, ReactNode, useContext, useEffect, useState } from "react";
|
import { createContext, ReactNode, useContext, useEffect, useState } from "react";
|
||||||
import { BaseTexture, Spritesheet, Texture } from "pixi.js";
|
import * as PIXI from "pixi.js";
|
||||||
|
|
||||||
import { LoadingContext } from "./Loading";
|
import { LoadingContext } from "./Loading";
|
||||||
|
|
||||||
import spritesheet from "@/data/blocks/programmer-art/spritesheet.json";
|
import spritesheet from "@/data/blocks/programmer-art/spritesheet.json";
|
||||||
|
import _blockData from "@/data/blocks/programmer-art/data.json";
|
||||||
|
const blockData: BlockData = _blockData;
|
||||||
|
|
||||||
interface Props {
|
interface Props {
|
||||||
children: ReactNode;
|
children: ReactNode;
|
||||||
}
|
}
|
||||||
|
|
||||||
export const TexturesContext = createContext({} as Record<string, Texture>);
|
export const TexturesContext = createContext({
|
||||||
|
textures: {} as Record<string, PIXI.Texture>,
|
||||||
|
solidTextures: {} as Record<string, PIXI.Texture>,
|
||||||
|
});
|
||||||
|
|
||||||
export const TexturesProvider = ({ children }: Props) => {
|
export const TexturesProvider = ({ children }: Props) => {
|
||||||
const [textures, setTextures] = useState<Record<string, Texture>>({});
|
|
||||||
const { setLoading } = useContext(LoadingContext);
|
const { setLoading } = useContext(LoadingContext);
|
||||||
|
|
||||||
|
const [textures, setTextures] = useState<Record<string, PIXI.Texture>>({});
|
||||||
|
const [solidTextures, setSolidTextures] = useState<Record<string, PIXI.Texture>>({});
|
||||||
|
|
||||||
useEffect(() => {
|
useEffect(() => {
|
||||||
const sheet = new Spritesheet(BaseTexture.from("/blocks/programmer-art/spritesheet.png"), spritesheet);
|
const sheet = new PIXI.Spritesheet(PIXI.BaseTexture.from("/blocks/programmer-art/spritesheet.png"), spritesheet);
|
||||||
sheet.parse().then((t) => {
|
sheet.parse().then((t) => {
|
||||||
setTextures(t);
|
setTextures(t);
|
||||||
setLoading(false);
|
|
||||||
});
|
});
|
||||||
|
|
||||||
|
// Load solid textures
|
||||||
|
const solidT: Record<string, PIXI.Texture> = {};
|
||||||
|
|
||||||
|
const canvas = document.createElement("canvas");
|
||||||
|
canvas.width = 16;
|
||||||
|
canvas.height = 16;
|
||||||
|
|
||||||
|
const ctx = canvas.getContext("2d");
|
||||||
|
if (!ctx) return;
|
||||||
|
|
||||||
|
Object.entries(blockData).forEach(([blockName, data]) => {
|
||||||
|
ctx.fillStyle = `rgb(${data.color[0]}, ${data.color[1]}, ${data.color[2]}, ${data.color[3]})`;
|
||||||
|
ctx.fillRect(0, 0, canvas.width, canvas.height);
|
||||||
|
|
||||||
|
const image = new Image();
|
||||||
|
image.src = canvas.toDataURL();
|
||||||
|
|
||||||
|
const baseTexture = new PIXI.BaseTexture(image);
|
||||||
|
const texture = new PIXI.Texture(baseTexture);
|
||||||
|
solidT[blockName] = texture;
|
||||||
|
});
|
||||||
|
|
||||||
|
setSolidTextures(solidT);
|
||||||
|
setLoading(false);
|
||||||
}, []);
|
}, []);
|
||||||
|
|
||||||
return <TexturesContext.Provider value={textures}>{children}</TexturesContext.Provider>;
|
return <TexturesContext.Provider value={{ textures, solidTextures }}>{children}</TexturesContext.Provider>;
|
||||||
};
|
};
|
||||||
|
|
|
||||||
Loading…
Reference in a new issue