Ebiten example - keyboard

// +build example

package main

import (
        "log"
        "strconv"

        "github.com/hajimehoshi/ebiten"
        "github.com/hajimehoshi/ebiten/ebitenutil"
        "github.com/hajimehoshi/ebiten/examples/keyboard/keyboard"
)

const (
        screenWidth  = 320
        screenHeight = 240
)

var keyboardImage *ebiten.Image

func init() {
        var err error
        keyboardImage, _, err = ebitenutil.NewImageFromFile("_resources/images/keyboard/keyboard.png", ebiten.FilterNearest)
        if err != nil {
                log.Fatal(err)
        }
}

var keyNames = map[ebiten.Key]string{
        ebiten.KeyBackspace: "BS",
        ebiten.KeyComma:     ",",
        ebiten.KeyDelete:    "Del",
        ebiten.KeyEnter:     "Enter",
        ebiten.KeyEscape:    "Esc",
        ebiten.KeyPeriod:    ".",
        ebiten.KeySpace:     "Space",
        ebiten.KeyTab:       "Tab",

        // Arrows
        ebiten.KeyDown:  "Down",
        ebiten.KeyLeft:  "Left",
        ebiten.KeyRight: "Right",
        ebiten.KeyUp:    "Up",

        // Mods
        ebiten.KeyShift:   "Shift",
        ebiten.KeyControl: "Ctrl",
        ebiten.KeyAlt:     "Alt",
}

type pressedKeysParts []string

func (p pressedKeysParts) Len() int {
        return len(p)
}

func (p pressedKeysParts) Dst(i int) (x0, y0, x1, y1 int) {
        k := p[i]
        r, ok := keyboard.KeyRect(k)
        if !ok {
                return 0, 0, 0, 0
        }
        return r.Min.X, r.Min.Y, r.Max.X, r.Max.Y
}

func (p pressedKeysParts) Src(i int) (x0, y0, x1, y1 int) {
        return p.Dst(i)
}

func update(screen *ebiten.Image) error {
        const offsetX, offsetY = 24, 40
        op := &ebiten.DrawImageOptions{}
        op.GeoM.Translate(offsetX, offsetY)
        op.ColorM.Scale(0.5, 0.5, 0.5, 1)
        screen.DrawImage(keyboardImage, op)

        pressed := []string{}
        for i := 0; i <= 9; i++ {
                if ebiten.IsKeyPressed(ebiten.Key(i) + ebiten.Key0) {
                        pressed = append(pressed, string(i+'0'))
                }
        }
        for c := 'A'; c <= 'Z'; c++ {
                if ebiten.IsKeyPressed(ebiten.Key(c) - 'A' + ebiten.KeyA) {
                        pressed = append(pressed, string(c))
                }
        }
        for i := 1; i <= 12; i++ {
                if ebiten.IsKeyPressed(ebiten.Key(i) + ebiten.KeyF1 - 1) {
                        pressed = append(pressed, "F"+strconv.Itoa(i))
                }
        }
        for key, name := range keyNames {
                if ebiten.IsKeyPressed(key) {
                        pressed = append(pressed, name)
                }
        }

        op = &ebiten.DrawImageOptions{
                ImageParts: pressedKeysParts(pressed),
        }
        op.GeoM.Translate(offsetX, offsetY)
        screen.DrawImage(keyboardImage, op)

        return nil
}

func main() {
        if err := ebiten.Run(update, screenWidth, screenHeight, 2, "Keyboard (Ebiten Demo)"); err != nil {
                log.Fatal(err)
        }
}