// browser specific code (keyboard handling and rendering)
package main
import (
"syscall/js"
)
// TODO PRIO2 interface KeyBoard
func (t *Tetris) KeyboardHandling() {
keydown := js.FuncOf(func(this js.Value, args []js.Value) interface{} {
event := args[0]
code := event.Get("code").String()
switch code {
case "ArrowLeft", "KeyJ":
t.move(-1, 0, t.rotation)
event.Call("preventDefault")
break
case "ArrowUp", "KeyK":
t.move(0, 0, (t.rotation+1)%4)
event.Call("preventDefault")
break
case "ArrowRight", "KeyL":
t.move(1, 0, t.rotation)
event.Call("preventDefault")
break
case "Space":
t.drop()
event.Call("preventDefault")
break
case "ArrowDown", "KeyI", "KeyM":
t.fall()
event.Call("preventDefault")
break
}
return nil
})
// TODO PRIO3 defer keyDown.Release() (atexit? onerror?)
js.Global().Get("window").
Call("addEventListener", "keydown", keydown)
}
const template = `
- Score
- 0
- Lines
- 0
`
type BrowserRenderer struct {
bucket, preview js.Value
score, lines js.Value
}
// TODO PRIO3 is it idiomatic to do more than init structures in Go?
func NewBrowserRenderer() *BrowserRenderer {
r := BrowserRenderer{}
document := js.Global().Get("document")
section := document.Call("querySelector", "section")
section.Set("innerHTML", template)
r.bucket = section.Call("querySelector", ".bucket")
r.preview = section.Call("querySelector", ".preview")
r.score = section.Call("querySelector", ".score")
r.lines = section.Call("querySelector", ".lines")
// bucket
for y := 0; y < HEIGHT; y++ {
row := r.bucket.Call("insertRow")
for x := 0; x < WIDTH; x++ {
row.Call("insertCell")
}
}
// preview
for y := 0; y < 4; y++ {
row := r.preview.Call("insertRow")
for x := 0; x < 4; x++ {
row.Call("insertCell")
}
}
return &r
}
func (r *BrowserRenderer) Draw(x, y int, color string) {
// little bit kludgy
if x < WIDTH {
row := r.bucket.Get("rows").Index(y)
cell := row.Get("cells").Index(x)
cell.Set("className", color)
} else {
row := r.preview.Get("rows").Index(y)
cell := row.Get("cells").Index(x - WIDTH)
cell.Set("className", color)
}
}
func (r *BrowserRenderer) Score(score, lines int) {
r.score.Set("textContent", score)
r.lines.Set("textContent", lines)
}
func (r *BrowserRenderer) GameOver() {
window := js.Global().Get("window")
window.Call("alert", "Game over :-(")
}