...

Source file src/code.rocketnine.space/tslocum/kibodo/demos/kibodo/game/game.go

Documentation: code.rocketnine.space/tslocum/kibodo/demos/kibodo/game

     1  package game
     2  
     3  import (
     4  	"fmt"
     5  
     6  	"github.com/hajimehoshi/ebiten/v2"
     7  	"github.com/hajimehoshi/ebiten/v2/ebitenutil"
     8  	"github.com/hajimehoshi/ebiten/v2/inpututil"
     9  )
    10  import "code.rocketnine.space/tslocum/kibodo"
    11  
    12  type game struct {
    13  	w, h int
    14  
    15  	k *kibodo.Keyboard
    16  
    17  	userInput []byte
    18  
    19  	incomingInput []*kibodo.Input
    20  
    21  	op *ebiten.DrawImageOptions
    22  
    23  	spinnerIndex int
    24  
    25  	buffer *ebiten.Image
    26  }
    27  
    28  var spinner = []byte(`-\|/`)
    29  
    30  // NewDemoGame returns a new kibodo demo game.
    31  func NewDemoGame() *game {
    32  	k := kibodo.NewKeyboard()
    33  	k.SetAllowUserHide(true)
    34  	k.SetPassThroughPhysicalInput(true)
    35  	k.SetKeys(kibodo.KeysQWERTY)
    36  	k.SetHideShortcuts([]ebiten.Key{ebiten.KeyEscape})
    37  
    38  	g := &game{
    39  		k: k,
    40  		op: &ebiten.DrawImageOptions{
    41  			Filter: ebiten.FilterNearest,
    42  		},
    43  	}
    44  
    45  	go g.showKeyboard()
    46  
    47  	return g
    48  }
    49  
    50  func (g *game) showKeyboard() {
    51  	if g.k.Visible() {
    52  		return
    53  	}
    54  
    55  	// Clear current input
    56  	g.userInput = nil
    57  
    58  	// Show keyboard
    59  	g.k.Show()
    60  }
    61  
    62  func (g *game) Layout(outsideWidth, outsideHeight int) (int, int) {
    63  	s := ebiten.DeviceScaleFactor()
    64  	outsideWidth, outsideHeight = int(float64(outsideWidth)*s), int(float64(outsideHeight)*s)
    65  	if g.w == outsideWidth && g.h == outsideHeight {
    66  		return outsideWidth, outsideHeight
    67  	}
    68  
    69  	g.w, g.h = outsideWidth, outsideHeight
    70  
    71  	g.buffer = ebiten.NewImage(g.w, g.h)
    72  
    73  	y := 200
    74  	if g.h > g.w && (g.h-g.w) > 200 {
    75  		y = g.h - g.w
    76  	}
    77  	g.k.SetRect(0, y, g.w, g.h-y)
    78  
    79  	return outsideWidth, outsideHeight
    80  }
    81  
    82  func (g *game) Update() error {
    83  	if inpututil.IsMouseButtonJustPressed(ebiten.MouseButtonLeft) && !g.k.Visible() {
    84  		g.showKeyboard()
    85  	}
    86  
    87  	g.incomingInput = g.k.AppendInput(g.incomingInput[:0])
    88  	for _, input := range g.incomingInput {
    89  		if input.Rune > 0 {
    90  			g.userInput = append(g.userInput, []byte(string(input.Rune))...)
    91  			continue
    92  		}
    93  		if input.Key == ebiten.KeyBackspace {
    94  			s := string(g.userInput)
    95  			if len(s) > 0 {
    96  				g.userInput = []byte(s[:len(s)-1])
    97  			}
    98  			continue
    99  		} else if input.Key == ebiten.KeyEnter {
   100  			g.userInput = nil
   101  			continue
   102  		} else if input.Key < 0 {
   103  			continue
   104  		}
   105  		g.userInput = append(g.userInput, []byte("<"+input.Key.String()+">")...)
   106  	}
   107  
   108  	return g.k.Update()
   109  }
   110  
   111  func (g *game) Draw(screen *ebiten.Image) {
   112  	g.k.Draw(screen)
   113  
   114  	g.buffer.Clear()
   115  	ebitenutil.DebugPrint(g.buffer, fmt.Sprintf("FPS %0.0f %c\nTPS %0.0f\n\n%s", ebiten.CurrentFPS(), spinner[g.spinnerIndex], ebiten.CurrentTPS(), g.userInput))
   116  	g.op.GeoM.Reset()
   117  	g.op.GeoM.Translate(3, 0)
   118  	g.op.GeoM.Scale(2, 2)
   119  	screen.DrawImage(g.buffer, g.op)
   120  
   121  	g.spinnerIndex++
   122  	if g.spinnerIndex == 4 {
   123  		g.spinnerIndex = 0
   124  	}
   125  }
   126  

View as plain text