New image loader
This commit is contained in:
parent
d1ab00c558
commit
877742cafb
|
|
@ -1,20 +0,0 @@
|
|||
import { plugin, type BunPlugin } from "bun";
|
||||
|
||||
const dataUrlPlugin: BunPlugin = {
|
||||
name: "Data-url loader",
|
||||
async setup(build) {
|
||||
build.onLoad({ filter: /\.(png)$/ }, async (args) => {
|
||||
const arrayBuffer = await Bun.file(args.path).arrayBuffer();
|
||||
const buffer = Buffer.from(arrayBuffer);
|
||||
|
||||
return {
|
||||
contents: `data:;base64,${buffer.toString('base64')}`,
|
||||
loader: 'text',
|
||||
};
|
||||
});
|
||||
}
|
||||
};
|
||||
|
||||
plugin(dataUrlPlugin);
|
||||
|
||||
export default dataUrlPlugin;
|
||||
|
|
@ -1,7 +1,7 @@
|
|||
import path from 'path';
|
||||
import { minify } from 'html-minifier';
|
||||
|
||||
import dataUrlPlugin from './dataUrlPlugin';
|
||||
import imagePlugin from './imagePlugin';
|
||||
import fontPlugin from './fontPlugin';
|
||||
import lightningcss from 'bun-lightningcss';
|
||||
|
||||
|
|
@ -22,7 +22,7 @@ export async function buildHTML(game: string, production = false) {
|
|||
GAMES: JSON.stringify(await getGames()),
|
||||
},
|
||||
plugins: [
|
||||
dataUrlPlugin,
|
||||
imagePlugin,
|
||||
fontPlugin,
|
||||
lightningcss(),
|
||||
]
|
||||
|
|
|
|||
|
|
@ -0,0 +1,24 @@
|
|||
import { plugin, type BunPlugin } from "bun";
|
||||
|
||||
const imagePlugin: BunPlugin = {
|
||||
name: "Image loader",
|
||||
async setup(build) {
|
||||
build.onLoad({ filter: /\.(png|jpe?g)$/ }, async (args) => {
|
||||
const arrayBuffer = await Bun.file(args.path).arrayBuffer();
|
||||
const buffer = Buffer.from(arrayBuffer);
|
||||
const src = `data:;base64,${buffer.toString('base64')}`;
|
||||
return {
|
||||
contents: `
|
||||
const img = new Image();
|
||||
img.src = (${JSON.stringify(src)});
|
||||
export default img;
|
||||
`,
|
||||
loader: 'js',
|
||||
};
|
||||
});
|
||||
}
|
||||
};
|
||||
|
||||
plugin(imagePlugin);
|
||||
|
||||
export default imagePlugin;
|
||||
|
|
@ -0,0 +1,12 @@
|
|||
declare module "*.png" {
|
||||
const image: HTMLImageElement;
|
||||
export default image;
|
||||
}
|
||||
declare module "*.jpg" {
|
||||
const image: HTMLImageElement;
|
||||
export default image;
|
||||
}
|
||||
declare module "*.jpeg" {
|
||||
const image: HTMLImageElement;
|
||||
export default image;
|
||||
}
|
||||
|
|
@ -1,3 +1,22 @@
|
|||
export const delay = async (ms: number) => new Promise((resolve) => setTimeout(resolve, ms));
|
||||
export const nextFrame = async (): Promise<number> => new Promise((resolve) => requestAnimationFrame(resolve));
|
||||
|
||||
export const randInt = (min: number, max: number) => Math.round(min + (max - min - 1) * Math.random());
|
||||
export const choice = (array: any[]) => array[randInt(0, array.length)];
|
||||
|
||||
export const range = (size: number | string) => Object.keys((new Array(+size)).fill(0)).map(k => +k);
|
||||
|
||||
export const prevent = (e: Event) => (e.preventDefault(), false);
|
||||
|
||||
export const intHash = (seed: number, ...parts: number[]) => {
|
||||
let h1 = 0xdeadbeef ^ seed, h2 = 0x41c6ce57 ^ seed;
|
||||
for (let i = 0; i < parts.length; i++) {
|
||||
const ch = parts[i];
|
||||
h1 = Math.imul(h1 ^ ch, 2654435761);
|
||||
h2 = Math.imul(h2 ^ ch, 1597334677);
|
||||
}
|
||||
h1 = Math.imul(h1 ^ (h1 >>> 16), 2246822507);
|
||||
h1 ^= Math.imul(h2 ^ (h2 >>> 13), 3266489909);
|
||||
return h1;
|
||||
};
|
||||
export const sinHash = (...data: number[]) => data.reduce((hash, n) => Math.sin((hash * 123.12 + n) * 756.12), 0) / 2 + 0.5;
|
||||
|
|
|
|||
|
|
@ -1,9 +1,10 @@
|
|||
import Graphics from "./graphics";
|
||||
import UI from "./ui";
|
||||
import World from "./world";
|
||||
import { pointsEquals, prevent } from "./utils";
|
||||
import { pointsEquals } from "./utils";
|
||||
import { prevent } from "@common/utils";
|
||||
|
||||
export default class Binario implements IGame {
|
||||
export default class Binario {
|
||||
private running = false;
|
||||
private mouseDown: false | number = false;
|
||||
private graphics;
|
||||
|
|
|
|||
|
|
@ -11,7 +11,6 @@ export default class Graphics {
|
|||
private offset: Point = [0, 0];
|
||||
private highlighted: Point = [0, 0];
|
||||
private tooltip: [Point, string] | null = null;
|
||||
private firstStyleReset = false;
|
||||
|
||||
constructor(private canvas: HTMLCanvasElement) {
|
||||
this.context = this.canvas.getContext('2d')!;
|
||||
|
|
|
|||
|
|
@ -1,12 +1,12 @@
|
|||
import { type Tile, TileType, getPortDirections, PortDirection, LIMITS, type Resource, getTileOutput, ResourceType } from "./world";
|
||||
import { type Tile, TileType, getPortDirections, PortDirection, type Resource, getTileOutput, ResourceType } from "./world";
|
||||
|
||||
import { ALL_DIRECTIONS, Direction, makeImage, movePoint } from "./utils";
|
||||
import { ALL_DIRECTIONS, Direction, movePoint } from "./utils";
|
||||
|
||||
import emptySrc from './assets/img/empty.png';
|
||||
import extractorSrc from './assets/img/extractor.png';
|
||||
import notSrc from './assets/img/not.png';
|
||||
import andSrc from './assets/img/and.png';
|
||||
import orSrc from './assets/img/or.png';
|
||||
import emptyImage from './assets/img/empty.png';
|
||||
import extractorImage from './assets/img/extractor.png';
|
||||
import notImage from './assets/img/not.png';
|
||||
import andImage from './assets/img/and.png';
|
||||
import orImage from './assets/img/or.png';
|
||||
|
||||
export interface ViewConfig {
|
||||
tileSize: number;
|
||||
|
|
@ -19,12 +19,6 @@ type Renderers = {
|
|||
[K in Tile['type']]?: Renderer<Extract<Tile, { type: K }>>
|
||||
}
|
||||
|
||||
const emptyImage = makeImage(emptySrc);
|
||||
const extractorImage = makeImage(extractorSrc);
|
||||
const notImage = makeImage(notSrc);
|
||||
const andImage = makeImage(andSrc);
|
||||
const orImage = makeImage(orSrc);
|
||||
|
||||
export const renderResource = (ctx: CanvasRenderingContext2D, view: ViewConfig, tile: Tile) => {
|
||||
let resources: [Direction, Resource | undefined][] | undefined;
|
||||
if (tile.type === TileType.SOURCE) {
|
||||
|
|
|
|||
|
|
@ -1,14 +1,14 @@
|
|||
import React, { render } from 'preact';
|
||||
import cn from 'classnames';
|
||||
import { range } from './utils';
|
||||
import { TileType } from './world';
|
||||
|
||||
import styles from './assets/ui.module.css';
|
||||
import conveyorSrc from './assets/img/conveyor.png';
|
||||
import extractorSrc from './assets/img/extractor.png';
|
||||
import notSrc from './assets/img/not.png';
|
||||
import andSrc from './assets/img/and.png';
|
||||
import orSrc from './assets/img/or.png';
|
||||
import conveyorImage from './assets/img/conveyor.png';
|
||||
import extractorImage from './assets/img/extractor.png';
|
||||
import notImage from './assets/img/not.png';
|
||||
import andImage from './assets/img/and.png';
|
||||
import orImage from './assets/img/or.png';
|
||||
import { range } from '@common/utils';
|
||||
|
||||
export enum ToolType {
|
||||
SELECT,
|
||||
|
|
@ -30,31 +30,31 @@ const TOOLS: (Tool | null)[] = [
|
|||
{
|
||||
type: ToolType.EXTRACTOR,
|
||||
title: 'Extractor',
|
||||
icon: extractorSrc,
|
||||
icon: extractorImage.src,
|
||||
tileType: TileType.EXTRACTOR,
|
||||
},
|
||||
{
|
||||
type: ToolType.CONVEYOR,
|
||||
title: 'Conveyor',
|
||||
icon: conveyorSrc,
|
||||
icon: conveyorImage.src,
|
||||
tileType: TileType.CONVEYOR,
|
||||
},
|
||||
{
|
||||
type: ToolType.NOT,
|
||||
title: 'Logical NOT',
|
||||
icon: notSrc,
|
||||
icon: notImage.src,
|
||||
tileType: TileType.NOT,
|
||||
},
|
||||
{
|
||||
type: ToolType.AND,
|
||||
title: 'Logical AND',
|
||||
icon: andSrc,
|
||||
icon: andImage.src,
|
||||
tileType: TileType.AND,
|
||||
},
|
||||
{
|
||||
type: ToolType.OR,
|
||||
title: 'Logical OR',
|
||||
icon: orSrc,
|
||||
icon: orImage.src,
|
||||
tileType: TileType.OR,
|
||||
},
|
||||
null, // 6
|
||||
|
|
|
|||
|
|
@ -105,22 +105,6 @@ export function trunc(input: Point): Point {
|
|||
const EPS = 0.001;
|
||||
export const pointsEquals = (a: Point, b: Point) => Math.abs(a[0] - b[0]) < EPS && Math.abs(a[1] - b[1]) < EPS;
|
||||
|
||||
export const prevent = (e: Event) => (e.preventDefault(), false);
|
||||
|
||||
export const cyrb32 = (seed: number, ...parts: number[]) => {
|
||||
let h1 = 0xdeadbeef ^ seed, h2 = 0x41c6ce57 ^ seed;
|
||||
for (let i = 0; i < parts.length; i++) {
|
||||
const ch = parts[i];
|
||||
h1 = Math.imul(h1 ^ ch, 2654435761);
|
||||
h2 = Math.imul(h2 ^ ch, 1597334677);
|
||||
}
|
||||
h1 = Math.imul(h1 ^ (h1 >>> 16), 2246822507);
|
||||
h1 ^= Math.imul(h2 ^ (h2 >>> 13), 3266489909);
|
||||
return h1;
|
||||
};
|
||||
export const sinHash = (...data: number[]) => data.reduce((hash, n) => Math.sin((hash * 123.12 + n) * 756.12), 0) / 2 + 0.5;
|
||||
export const range = (size: number | string) => Object.keys((new Array(+size)).fill(0)).map(k => +k);
|
||||
|
||||
export const getDirection = (point: Point): Direction => {
|
||||
const [x, y] = point;
|
||||
const absX = Math.abs(x);
|
||||
|
|
@ -158,9 +142,3 @@ export const movePoint = (point: Point, direction: Direction, scale: number = 1)
|
|||
point[0] + DIRECTION_VECTORS[direction][0] * scale,
|
||||
point[1] + DIRECTION_VECTORS[direction][1] * scale,
|
||||
];
|
||||
|
||||
export const makeImage = (src: string): HTMLImageElement => {
|
||||
const image = new Image();
|
||||
image.src = src;
|
||||
return image;
|
||||
}
|
||||
|
|
@ -1,4 +1,5 @@
|
|||
import { ALL_DIRECTIONS, Direction, NEXT_DIRECTION, cyrb32, exp, getDirection, getOppositeDirection, isDirection, movePoint, pointsEquals, trunc } from "./utils";
|
||||
import { intHash } from "@common/utils";
|
||||
import { ALL_DIRECTIONS, Direction, NEXT_DIRECTION, exp, getDirection, getOppositeDirection, isDirection, movePoint, pointsEquals, trunc } from "./utils";
|
||||
|
||||
export enum TileType {
|
||||
DESTINATION,
|
||||
|
|
@ -343,7 +344,7 @@ export default class World {
|
|||
}
|
||||
|
||||
private genTile(position: Point): Tile | null {
|
||||
const hash = cyrb32(this.seed, ...position);
|
||||
const hash = intHash(this.seed, ...position);
|
||||
|
||||
if ([42, 69, 0x42, 0x69].includes(hash & 0xFF)) {
|
||||
let mask = 1;
|
||||
|
|
|
|||
|
|
@ -1,7 +1,5 @@
|
|||
|
||||
|
||||
import '@common/assets/vga.font.css';
|
||||
import './assets/style.css';
|
||||
import './assets/vga.font.css';
|
||||
|
||||
export default async function run(canvas: HTMLCanvasElement) {
|
||||
canvas.remove();
|
||||
|
|
|
|||
|
|
@ -6,8 +6,6 @@ export const randChar = (min = ' ', max = '~') =>
|
|||
max.charCodeAt(0) + 1,
|
||||
));
|
||||
|
||||
export const choice = (array: any[]) => array[randInt(0, array.length)];
|
||||
|
||||
export const generateColors = () => {
|
||||
const colors: string[] = [];
|
||||
for (let i = 0; i < 16; i++) {
|
||||
|
|
|
|||
|
|
@ -3,10 +3,6 @@ type Rect = [number, number, number, number];
|
|||
|
||||
type RunGame = (canvas: HTMLCanvasElement) => Promise<void>;
|
||||
|
||||
declare module "*.png" {
|
||||
const content: string;
|
||||
export default content;
|
||||
}
|
||||
declare module '*.module.css' {
|
||||
const classes: { [key: string]: string };
|
||||
export default classes;
|
||||
|
|
|
|||
Loading…
Reference in New Issue