1
0
mirror of https://github.com/taigrr/wasm-experiments synced 2025-01-18 04:03:21 -08:00
2019-06-23 15:08:02 +01:00

198 lines
4.2 KiB
Go

// +build js,wasm
package main
import (
"math"
"math/rand"
"strconv"
"syscall/js"
)
var (
width float64
height float64
mousePos [2]float64
ctx, doc js.Value
canvasEl js.Value
dt DotThing
tmark float64
markCount = 0
tdiffSum float64
)
func main() {
// Init Canvas stuff
doc = js.Global().Get("document")
canvasEl = doc.Call("getElementById", "mycanvas")
width = doc.Get("body").Get("clientWidth").Float()
height = doc.Get("body").Get("clientHeight").Float()
canvasEl.Call("setAttribute", "width", width)
canvasEl.Call("setAttribute", "height", height)
ctx = canvasEl.Call("getContext", "2d")
// Set up dot thing
dt = DotThing{speed: 160}
dt.SetNDots(100)
dt.lines = false
js.Global().Call("requestAnimationFrame", js.Global().Get("renderFrame"))
}
// * Handlers for JS callback functions *
//go:export speedInput
func speedInput(fval float64) {
dt.speed = fval
}
//go:export countChange
func countChange(intVal int) {
dt.SetNDots(intVal)
}
//go:export moveHandler
func moveHandler(cx int, cy int) {
mousePos[0] = float64(cx)
mousePos[1] = float64(cy)
}
//go:export renderFrame
func renderFrame(now float64) {
tdiff := now - tmark
tdiffSum += now - tmark
markCount++
if markCount > 10 {
doc.Call("getElementById", "fps").Set("innerHTML", "FPS: "+strconv.FormatFloat(1000/(tdiffSum/float64(markCount)), 'f', 1, 64))
tdiffSum, markCount = 0, 0
}
tmark = now
// Pool window size to handle resize
curBodyW := doc.Get("body").Get("clientWidth").Float()
curBodyH := doc.Get("body").Get("clientHeight").Float()
if curBodyW != width || curBodyH != height {
width, height = curBodyW, curBodyH
canvasEl.Set("width", width)
canvasEl.Set("height", height)
}
dt.Update(tdiff / 1000)
js.Global().Call("requestAnimationFrame", js.Global().Get("renderFrame"))
}
// DotThing manager
type DotThing struct {
dots []*Dot
lines bool
speed float64
}
// Update updates the dot positions and draws
func (dt *DotThing) Update(dtTime float64) {
if dt.dots == nil {
return
}
ctx.Call("clearRect", 0, 0, width, height)
// Update
for i, dot := range dt.dots {
if dot.pos[0] < dot.size {
dot.pos[0] = dot.size
dot.dir[0] *= -1
}
if dot.pos[0] > width-dot.size {
dot.pos[0] = width - dot.size
dot.dir[0] *= -1
}
if dot.pos[1] < dot.size {
dot.pos[1] = dot.size
dot.dir[1] *= -1
}
if dot.pos[1] > height-dot.size {
dot.pos[1] = height - dot.size
dot.dir[1] *= -1
}
mdx := mousePos[0] - dot.pos[0]
mdy := mousePos[1] - dot.pos[1]
d := math.Sqrt(mdx*mdx + mdy*mdy)
if d < 200 {
dInv := 1 - d/200
dot.dir[0] += (-mdx / d) * dInv * 8
dot.dir[1] += (-mdy / d) * dInv * 8
}
for j, dot2 := range dt.dots {
if i == j {
continue
}
mx := dot2.pos[0] - dot.pos[0]
my := dot2.pos[1] - dot.pos[1]
d := math.Sqrt(mx*mx + my*my)
if d < 100 {
dInv := 1 - d/100
dot.dir[0] += (-mx / d) * dInv
dot.dir[1] += (-my / d) * dInv
}
}
dot.dir[0] *= 0.1 //friction
dot.dir[1] *= 0.1 //friction
dot.pos[0] += dot.dir[0] * dt.speed * dtTime * 10
dot.pos[1] += dot.dir[1] * dt.speed * dtTime * 10
ctx.Set("globalAlpha", 0.5)
ctx.Call("beginPath")
hexCol := hexFormat(dot.color)
ctx.Set("fillStyle", hexCol)
ctx.Set("strokeStyle", hexCol)
ctx.Set("lineWidth", dot.size)
ctx.Call("arc", dot.pos[0], dot.pos[1], dot.size, 0, 2*math.Pi)
ctx.Call("fill")
}
}
// SetNDots reinitializes dots with n size
func (dt *DotThing) SetNDots(n int) {
dt.dots = make([]*Dot, n)
for i := 0; i < n; i++ {
dt.dots[i] = &Dot{
pos: [2]float64{
rand.Float64() * width,
rand.Float64() * height,
},
dir: [2]float64{
rand.NormFloat64(),
rand.NormFloat64(),
},
color: uint32(rand.Intn(0xFFFFFF)),
size: 10,
}
}
}
// Adapted from the Go source: https://github.com/golang/go/blob/4ce6a8e89668b87dce67e2f55802903d6eb9110a/src/fmt/format.go#L248-L252
func hexFormat(u uint32) string {
digits := "0123456789abcdefx"
buf := make([]uint8, 6)
i := len(buf)
for u >= 16 {
i--
buf[i] = digits[u&0xF]
u >>= 4
}
i--
buf[i] = digits[u]
return "#" + string(buf)
}
// Dot represents a dot ...
type Dot struct {
pos [2]float64
dir [2]float64
color uint32
size float64
}