Set up server to relay ripples and presence info
This commit is contained in:
parent
398aa43338
commit
8ccb60de61
7 changed files with 338 additions and 7 deletions
|
|
@ -1,4 +1,9 @@
|
|||
const canvas = document.querySelector<HTMLCanvasElement>('#canvas')!
|
||||
const socket = new WebSocket(`ws://${window.location.hostname}:3000`)
|
||||
|
||||
type Message =
|
||||
| { type: 'presence-information', others: number }
|
||||
| { type: 'ripple', position: [number, number], maxRadius: number }
|
||||
|
||||
const ctx = canvas.getContext('2d')!
|
||||
|
||||
|
|
@ -14,24 +19,38 @@ type Particle = {
|
|||
maxRadius: number
|
||||
}
|
||||
|
||||
const createParticle = (position: [number, number], maxRadius: number): Particle => ({
|
||||
position,
|
||||
maxRadius,
|
||||
age: 0,
|
||||
})
|
||||
|
||||
let state = {
|
||||
particles: <Particle[]>[]
|
||||
}
|
||||
|
||||
type State = typeof state
|
||||
|
||||
canvas.addEventListener('mousedown', (e) => {
|
||||
// TODO Normalize x and y coords
|
||||
const particle = createParticle([e.clientX, e.clientY], MAX_RADIUS)
|
||||
state.particles.push(particle)
|
||||
const createParticle = (position: [number, number], maxRadius: number): Particle => ({
|
||||
position,
|
||||
maxRadius,
|
||||
age: 0,
|
||||
})
|
||||
|
||||
const makeRipple = (position: [number, number], radius: number): void => {
|
||||
const particle = createParticle(position, radius)
|
||||
socket.send(JSON.stringify(<Message>{
|
||||
type: 'ripple',
|
||||
position: particle.position,
|
||||
maxRadius: particle.maxRadius,
|
||||
}))
|
||||
state.particles.push(particle)
|
||||
}
|
||||
|
||||
// event handlers
|
||||
|
||||
// create a big ripple when touching the screen
|
||||
canvas.addEventListener('mousedown', (e) => {
|
||||
// TODO Normalize x and y coords
|
||||
const radius = MAX_RADIUS
|
||||
makeRipple([e.clientX, e.clientY], radius)
|
||||
})
|
||||
|
||||
// create a smaller ripple when moving over the screen
|
||||
function* minDist(dist: number) {
|
||||
let prev: Point
|
||||
while (true) {
|
||||
|
|
@ -50,11 +69,33 @@ const hasSpace = minDist(70)
|
|||
canvas.addEventListener('mousemove', (e) => {
|
||||
const shouldSpawn = hasSpace.next().value!
|
||||
if (shouldSpawn([e.clientX, e.clientY])) {
|
||||
const particle = createParticle([e.clientX, e.clientY], MAX_RADIUS / 3*2)
|
||||
state.particles.push(particle)
|
||||
const radius = MAX_RADIUS / 3*2
|
||||
makeRipple([e.clientX, e.clientY], radius)
|
||||
}
|
||||
})
|
||||
|
||||
// react to incoming websocket messages
|
||||
socket.addEventListener('message', (e) => {
|
||||
console.log('Received websocket message', e)
|
||||
if (typeof e.data === 'string') {
|
||||
// TODO: Validate message shape
|
||||
const message = JSON.parse(e.data)
|
||||
if (message?.type === 'presence-information') {
|
||||
const data = <Message & { type: 'presence-information' }>message
|
||||
console.log(`i'm seeing ${data.others} others around the pond`)
|
||||
} else if (message?.type === 'ripple') {
|
||||
const data = <Message & { type: 'ripple' }>message
|
||||
const particle = createParticle(data.position, data.maxRadius)
|
||||
state.particles.push(particle)
|
||||
}
|
||||
} else {
|
||||
console.warn('i received an odd message and i don\'t know what to do with it', e.data)
|
||||
}
|
||||
})
|
||||
|
||||
// main loop
|
||||
|
||||
// update the particles and remove them after a certain time
|
||||
const update = (state: State, deltaTime: number): State => ({
|
||||
particles: state.particles
|
||||
.map(p => ({
|
||||
|
|
@ -64,6 +105,7 @@ const update = (state: State, deltaTime: number): State => ({
|
|||
.filter(p => p.age < MAX_AGE)
|
||||
})
|
||||
|
||||
// draw particles
|
||||
const render = (state: State, ctx: CanvasRenderingContext2D) => {
|
||||
ctx.clearRect(0, 0, ctx.canvas.width, ctx.canvas.height)
|
||||
|
||||
|
|
@ -90,6 +132,7 @@ const loop = () => {
|
|||
requestAnimationFrame(loop)
|
||||
}
|
||||
|
||||
// start everything
|
||||
document.addEventListener('DOMContentLoaded', () => {
|
||||
canvas.width = canvas.parentElement!.clientWidth
|
||||
canvas.height = canvas.parentElement!.clientHeight
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue