Render positions

No frame syncs, so flickers terribly, and performance is garbage. But it
works.
This commit is contained in:
Gender Shrapnel 2020-08-23 03:50:58 +02:00
parent b26a39a461
commit 53487944bc
9 changed files with 127 additions and 30 deletions

View File

@ -31,7 +31,11 @@ module.exports = {
asyncArrow: "always" asyncArrow: "always"
}], }],
"quote-props": ["error", "consistent"], "quote-props": ["error", "consistent"],
"quotes": ["error", "double"] "quotes": ["error", "double"],
"sort-imports": ["error", {
"ignoreCase": true,
"allowSeparatedGroups": true
}]
}, },
overrides: [ overrides: [
{ {

33
src/components/Canvas.tsx Normal file
View File

@ -0,0 +1,33 @@
import React from "react"
import CanvasContext from "./CanvasContext"
export interface SystemCanvasProps {
height: number,
width: number,
children?: JSX.Element[]
}
function SystemCanvas({ height, width, children }: SystemCanvasProps) {
const canvasRef = React.useRef<HTMLCanvasElement>(null)
const [context, setContext] = React.useState<CanvasRenderingContext2D>(null)
React.useEffect(() => {
const context = canvasRef.current.getContext("2d")
context.save()
context.fillStyle = "black"
context.fillRect(0, 0, width, height)
context.restore()
setContext(context)
})
return (<div>
<CanvasContext.Provider value={ context }>
<canvas width={width} height={height} ref={canvasRef} style={{ width, height }} />
{children}
</CanvasContext.Provider>
</div>
)
}
export default SystemCanvas

View File

@ -0,0 +1,5 @@
import React from "react"
const CanvasContext = React.createContext<CanvasRenderingContext2D | null>(null)
export default CanvasContext

View File

@ -1,17 +1,19 @@
import React, { useState, useEffect } from "react" import React, { useEffect, useState } from "react"
import { Message, Object } from "@app/types" import { Body, Bounds, Message } from "@app/types"
import Canvas from "./Canvas"
import Client from "@app/client" import Client from "@app/client"
import ObjectList from "./ObjectList" import RenderedBody from "./RenderedBody"
function Home() { function Home() {
const [objects, setObjects] = useState<Object[]>([]) const [bodies, setBodies] = useState<Body[]>([])
const [iteration, setIteration] = useState(0) const [iteration, setIteration] = useState(0)
const [messageCount, setMessageCount] = useState(0) const [messageCount, setMessageCount] = useState(0)
const [client, setClient] = useState<Client|null>(null) const [client, setClient] = useState<Client|null>(null)
const [bounds, setBounds] = useState<Bounds>(new Bounds(0, 0, 30, 30))
const handleMessage = (msg: Message) => { const handleMessage = (msg: Message) => {
setObjects(msg.objects) setBodies(msg.objects)
setIteration(msg.iteration) setIteration(msg.iteration)
setMessageCount((mc) => mc + 1) setMessageCount((mc) => mc + 1)
} }
@ -31,11 +33,29 @@ function Home() {
} }
}, [client, messageCount]) }, [client, messageCount])
useEffect(() => {
setBounds((bounds) => bodies.reduce(
(bounds, obj) => new Bounds(
Math.min(obj.x, bounds.minX),
Math.min(obj.y, bounds.minY),
Math.max(obj.x, bounds.maxX),
Math.max(obj.y, bounds.maxY)), bounds))
}, [bodies])
const actualBounds = new Bounds(0, 0, 300, 300)
return ( return (
<> <>
<h1>Hello, World!</h1> <h1>Hello, World!</h1>
<p>Iteration: { iteration }, message count: { messageCount }.</p> <p>Iteration: { iteration }, message count: { messageCount }, nObjects: { bodies.length }.</p>
<ObjectList objects={objects} /> <Canvas height={actualBounds.height} width={actualBounds.width}>
{bodies.map((body) => <RenderedBody
key={body.id}
body={body}
bounds={bounds}
actualBounds={actualBounds}
/>)}
</Canvas>
</> </>
) )
} }

View File

@ -1,15 +0,0 @@
import React from "react"
import { Object } from "@app/types"
export interface ObjectListProps {
objects: Object[]
}
function ObjectList({ objects }: ObjectListProps) {
return (<ul>
{objects.map((o) => <li key={o.id}>{o.name} @ ({o.x}, {o.y}, {o.z}) </li>)}
</ul>)
}
export default ObjectList

View File

@ -0,0 +1,33 @@
import React from "react"
import { Body, Bounds } from "types"
import CanvasContext from "./CanvasContext"
export interface RenderedBodyProps {
body: Body
bounds: Bounds
actualBounds: Bounds
}
function RenderedBody({ body, bounds, actualBounds } : RenderedBodyProps): JSX.Element {
const context = React.useContext(CanvasContext)
if (context === null) {
return
}
const xScale = actualBounds.width / bounds.width
const yScale = actualBounds.height / bounds.width
context.save()
context.scale(xScale, yScale)
context.translate(-bounds.minX, -bounds.minY)
context.fillStyle = "white"
context.beginPath()
context.ellipse(body.x, body.y, 1 / xScale, 1 / yScale, 0, 0, Math.PI * 2)
context.fill()
context.restore()
return null
}
export default RenderedBody

View File

@ -1,6 +1,6 @@
import React from 'react' import React from "react"
import ReactDOM from 'react-dom' import ReactDOM from "react-dom"
import Home from '@app/components/Home' import Home from "@app/components/Home"
ReactDOM.render(<Home />, document.getElementById('root')) ReactDOM.render(<Home />, document.getElementById("root"))

View File

@ -1,4 +1,4 @@
export interface Object { export interface Body {
name: string, name: string,
id: number, id: number,
x: number, x: number,
@ -8,5 +8,22 @@ export interface Object {
export interface Message { export interface Message {
iteration: number, iteration: number,
objects: Object[] objects: Body[]
}
export class Bounds {
minX: number
minY: number
maxX: number
maxY: number
constructor(minX: number, minY: number, maxX: number, maxY: number) {
this.minX = minX
this.minY = minY
this.maxX = maxX
this.maxY = maxY
}
get width() { return this.maxX - this.minX }
get height() { return this.maxY - this.minY }
} }

View File

@ -13,4 +13,4 @@
"@app/*": ["../src/*"] "@app/*": ["../src/*"]
} }
} }
} }