make react component
This commit is contained in:
parent
55fca0a5c2
commit
d606a8002f
33
TODO.md
33
TODO.md
@ -1,15 +1,20 @@
|
|||||||
TODO
|
# TODO
|
||||||
|
|
||||||
- [ ] User Auth
|
## MVP
|
||||||
- [x] Component Pack
|
- [ ] Update GH Workflow to be by push
|
||||||
- [x] Typescript Pack
|
- [ ] Add version prop to picobook.json
|
||||||
- [ ] Can this be used in a way where it doesn't need to be imported everywhere (lib?)
|
- [ ] "Compile" carts in server and save them to db
|
||||||
- [ ] Consider making more parts into Packs
|
- [ ] Load cart by URL in React
|
||||||
- [ ] tsconfig with extends
|
|
||||||
- [ ] server with wrapper around fastify
|
## Later
|
||||||
- [ ] scripts from package.json
|
- [ ] Update pico console handle
|
||||||
- [ ] Streamline spinning up a server
|
- [ ] Add readme prop to picobook.json (figure out best name) and display it in React
|
||||||
- [ ] Should public be top level?
|
- [ ] Multiplayer support
|
||||||
- [ ] Clean up .env variable names
|
- [ ] More console support (touch detected, gamepad count, etc.)
|
||||||
- [ ] use Temporal (polyfill)?
|
- [ ] User accounts to manage published games, and user accounts for players to save progress
|
||||||
- [ ] Do I want to add testing infrastructure?
|
- [ ] GPIO Support (maybe gpio prop in picobook.json can have values like "ignore" | "v1")
|
||||||
|
|
||||||
|
## GPIO ideas
|
||||||
|
- RGB background color
|
||||||
|
- Awards
|
||||||
|
- Extra buttons?
|
@ -1,34 +1,16 @@
|
|||||||
import { css } from "@emotion/css";
|
import { css } from "@emotion/css";
|
||||||
import { Center, Cover, Stack } from "@firebox/components";
|
import { Center, Cover, Stack } from "@firebox/components";
|
||||||
|
import { Pico8Console } from "./pico8-client/Pico8Console";
|
||||||
|
import testcarts from "./testcarts";
|
||||||
|
|
||||||
const App = (props: { name: string }) => {
|
const App = (props: {}) => {
|
||||||
const {name} = props;
|
|
||||||
return (
|
return (
|
||||||
<Stack>
|
<div className={css`
|
||||||
<div className={css`background-color: floralwhite;`}>
|
min-height: 100vh;
|
||||||
<Cover gap pad>
|
`}>
|
||||||
<Center>
|
<Pico8Console carts={testcarts.carts} />
|
||||||
<Stack gap={-1}>
|
</div>
|
||||||
<h1>Hello, {name}!</h1>
|
|
||||||
<p>Welcome to a website with a certain design philosophy. Tell me how it's working out! I want to see this text wrap a few times. Hopefully this sentence will help.</p>
|
|
||||||
</Stack>
|
|
||||||
</Center>
|
|
||||||
<Cover.Footer>A page by Dylan Pizzo</Cover.Footer>
|
|
||||||
</Cover>
|
|
||||||
</div>
|
|
||||||
<div className={css`background-color: aliceblue;`}>
|
|
||||||
<Cover gap pad>
|
|
||||||
<Center>
|
|
||||||
<Stack gap={-1}>
|
|
||||||
<h1>Hello, {name}!</h1>
|
|
||||||
<p>Welcome to a website with a certain design philosophy. Tell me how it's working out! I want to see this text wrap a few times. Hopefully this sentence will help.</p>
|
|
||||||
</Stack>
|
|
||||||
</Center>
|
|
||||||
<Cover.Footer>A page by Dylan Pizzo</Cover.Footer>
|
|
||||||
</Cover>
|
|
||||||
</div>
|
|
||||||
</Stack>
|
|
||||||
);
|
);
|
||||||
};
|
};
|
||||||
|
|
||||||
export const app = <App name="World" />;
|
export const app = <App />;
|
||||||
|
@ -1,8 +1,8 @@
|
|||||||
// import { createRoot } from "react-dom/client";
|
import { createRoot } from "react-dom/client";
|
||||||
// import { app } from "./app.js";
|
import { app } from "./app.js";
|
||||||
|
|
||||||
// const domNode = document.getElementById("root")!;
|
const domNode = document.getElementById("root")!;
|
||||||
// const root = createRoot(domNode);
|
const root = createRoot(domNode);
|
||||||
// root.render(app);
|
root.render(app);
|
||||||
|
|
||||||
export * from "./pico8-client/index";
|
// export * from "./pico8-client/index";
|
44
src/client/pico8-client/Pico8Console.tsx
Normal file
44
src/client/pico8-client/Pico8Console.tsx
Normal file
@ -0,0 +1,44 @@
|
|||||||
|
import { css } from "@emotion/css";
|
||||||
|
import { PicoCart, PicoPlayerHandle, makePicoConsole } from "./renderCart";
|
||||||
|
import { ForwardedRef, forwardRef, useCallback, useEffect, useImperativeHandle, useRef, useState } from "react";
|
||||||
|
|
||||||
|
type Pico8ConsoleImperatives = {
|
||||||
|
getPicoConsoleHandle(): PicoPlayerHandle | null;
|
||||||
|
}
|
||||||
|
|
||||||
|
export const Pico8Console = forwardRef((props: { carts: PicoCart[] }, forwardedRef: ForwardedRef<Pico8ConsoleImperatives>) => {
|
||||||
|
const {carts} = props;
|
||||||
|
const ref = useRef<HTMLDivElement>(null);
|
||||||
|
const [handle, setHandle] = useState<PicoPlayerHandle | null>(null);
|
||||||
|
const attachConsole = useCallback(async () => {
|
||||||
|
const picoConsole = await makePicoConsole({
|
||||||
|
carts,
|
||||||
|
});
|
||||||
|
if (ref.current) {
|
||||||
|
ref.current.appendChild(picoConsole.canvas);
|
||||||
|
}
|
||||||
|
setHandle(picoConsole);
|
||||||
|
}, [carts]);
|
||||||
|
useImperativeHandle(forwardedRef, () => ({
|
||||||
|
getPicoConsoleHandle() {
|
||||||
|
return handle;
|
||||||
|
}
|
||||||
|
}), [handle]);
|
||||||
|
useEffect(() => {
|
||||||
|
attachConsole();
|
||||||
|
}, [attachConsole]);
|
||||||
|
return (
|
||||||
|
<div ref={ref} className={css`
|
||||||
|
width: 100%;
|
||||||
|
height: 100%;
|
||||||
|
display: flex;
|
||||||
|
align-items: center;
|
||||||
|
justify-content: center;
|
||||||
|
|
||||||
|
& > canvas {
|
||||||
|
width: 100%;
|
||||||
|
height: 100%;
|
||||||
|
}
|
||||||
|
`}></div>
|
||||||
|
);
|
||||||
|
});
|
@ -1,9 +1,9 @@
|
|||||||
// @ts-ignore
|
// @ts-ignore
|
||||||
import "./build/veryRawRenderCart.js";
|
import "./build/veryRawRenderCart.js";
|
||||||
|
|
||||||
type PicoBool = 0 | 1;
|
export type PicoBool = 0 | 1;
|
||||||
|
|
||||||
type RenderCart = (Module: {canvas: HTMLCanvasElement}, cartNames: string[], cartDatas: number[][], audioContext: AudioContext) => {
|
export type RenderCart = (Module: {canvas: HTMLCanvasElement}, cartNames: string[], cartDatas: number[][], audioContext: AudioContext) => {
|
||||||
p8_touch_detected?: PicoBool;
|
p8_touch_detected?: PicoBool;
|
||||||
p8_dropped_cart?: string;
|
p8_dropped_cart?: string;
|
||||||
p8_dropped_cart_name?: string;
|
p8_dropped_cart_name?: string;
|
||||||
|
@ -1,8 +1,8 @@
|
|||||||
import { assertNever } from "@firebox/tsutil";
|
import { assertNever } from "@firebox/tsutil";
|
||||||
import { pngToRom } from "./pngToRom";
|
import { pngToRom } from "./pngToRom";
|
||||||
import { renderCart as rawRenderCart } from "./rawRenderCart";
|
import { RenderCart, renderCart as rawRenderCart } from "./rawRenderCart";
|
||||||
|
|
||||||
type PicoCart = {
|
export type PicoCart = {
|
||||||
name: string;
|
name: string;
|
||||||
src: string;
|
src: string;
|
||||||
} | {
|
} | {
|
||||||
@ -20,7 +20,9 @@ type PlayerButtons = {
|
|||||||
menu: boolean;
|
menu: boolean;
|
||||||
}
|
}
|
||||||
|
|
||||||
type PicoPlayerHandle = {
|
export type PicoPlayerHandle = {
|
||||||
|
raw: ReturnType<RenderCart>;
|
||||||
|
rawModule: unknown;
|
||||||
// external things
|
// external things
|
||||||
readonly canvas: HTMLCanvasElement;
|
readonly canvas: HTMLCanvasElement;
|
||||||
|
|
||||||
@ -35,16 +37,16 @@ type PicoPlayerHandle = {
|
|||||||
setGamepadCount: (count: number) => void;
|
setGamepadCount: (count: number) => void;
|
||||||
readonly gpio: number[]; // read + write (should be 256-tuple)
|
readonly gpio: number[]; // read + write (should be 256-tuple)
|
||||||
|
|
||||||
// state (all communicated out)
|
// state
|
||||||
readonly state: {
|
readonly state: {
|
||||||
readonly frameNumber: number;
|
frameNumber: number;
|
||||||
readonly isPaused: boolean;
|
isPaused: boolean;
|
||||||
readonly hasFocus: boolean;
|
hasFocus: boolean;
|
||||||
readonly requestPointerLock: boolean;
|
requestPointerLock: boolean;
|
||||||
readonly requirePageNavigateConfirmation: boolean;
|
requirePageNavigateConfirmation: boolean;
|
||||||
readonly showDpad: boolean;
|
showDpad: boolean;
|
||||||
readonly shutdownRequested: boolean;
|
shutdownRequested: boolean;
|
||||||
readonly soundVolume: number;
|
soundVolume: number;
|
||||||
};
|
};
|
||||||
|
|
||||||
// misc?
|
// misc?
|
||||||
@ -109,6 +111,8 @@ export const makePicoConsole = async (props: {
|
|||||||
];
|
];
|
||||||
handle.pico8_gamepads = {count: 0};
|
handle.pico8_gamepads = {count: 0};
|
||||||
return {
|
return {
|
||||||
|
raw: handle,
|
||||||
|
rawModule: Module,
|
||||||
canvas,
|
canvas,
|
||||||
state: {
|
state: {
|
||||||
frameNumber: handle.pico8_state.frame_number!,
|
frameNumber: handle.pico8_state.frame_number!,
|
||||||
|
21
src/client/testcarts.ts
Normal file
21
src/client/testcarts.ts
Normal file
File diff suppressed because one or more lines are too long
@ -3,11 +3,6 @@
|
|||||||
<meta name="viewport" content="width=device-width, user-scalable=no">
|
<meta name="viewport" content="width=device-width, user-scalable=no">
|
||||||
<script type="text/javascript">
|
<script type="text/javascript">
|
||||||
|
|
||||||
console.log(Object.keys(window));
|
|
||||||
setTimeout(() => {
|
|
||||||
console.log(Object.keys(window));
|
|
||||||
}, 1000);
|
|
||||||
|
|
||||||
// Default shell for PICO-8 0.2.2 (includes @weeble's gamepad mod 1.0)
|
// Default shell for PICO-8 0.2.2 (includes @weeble's gamepad mod 1.0)
|
||||||
// This file is available under a CC0 license https://creativecommons.org/share-your-work/public-domain/cc0/
|
// This file is available under a CC0 license https://creativecommons.org/share-your-work/public-domain/cc0/
|
||||||
// (note: "this file" does not include any cartridge or cartridge artwork injected into a derivative html file when using the PICO-8 html exporter)
|
// (note: "this file" does not include any cartridge or cartridge artwork injected into a derivative html file when using the PICO-8 html exporter)
|
||||||
|
Loading…
x
Reference in New Issue
Block a user