add basic viewer
This commit is contained in:
parent
d41e310aa3
commit
274cda86bb
14
go.mod
14
go.mod
@ -1,3 +1,17 @@
|
|||||||
module git.saintnet.tech/freego
|
module git.saintnet.tech/freego
|
||||||
|
|
||||||
go 1.17
|
go 1.17
|
||||||
|
|
||||||
|
require (
|
||||||
|
github.com/go-gl/glfw/v3.3/glfw v0.0.0-20211213063430-748e38ca8aec // indirect
|
||||||
|
github.com/hajimehoshi/ebiten v1.12.12 // indirect
|
||||||
|
github.com/hajimehoshi/ebiten/v2 v2.2.5 // indirect
|
||||||
|
github.com/jezek/xgb v1.0.0 // indirect
|
||||||
|
golang.org/x/exp v0.0.0-20190731235908-ec7cb31e5a56 // indirect
|
||||||
|
golang.org/x/exp/shiny v0.0.0-20220218215828-6cf2b201936e // indirect
|
||||||
|
golang.org/x/image v0.0.0-20211028202545-6944b10bf410 // indirect
|
||||||
|
golang.org/x/mobile v0.0.0-20220112015953-858099ff7816 // indirect
|
||||||
|
golang.org/x/sync v0.0.0-20210220032951-036812b2e83c // indirect
|
||||||
|
golang.org/x/sys v0.0.0-20220209214540-3681064d5158 // indirect
|
||||||
|
golang.org/x/text v0.3.6 // indirect
|
||||||
|
)
|
||||||
|
206
input.go
Normal file
206
input.go
Normal file
@ -0,0 +1,206 @@
|
|||||||
|
package main
|
||||||
|
|
||||||
|
import (
|
||||||
|
"github.com/hajimehoshi/ebiten/v2"
|
||||||
|
"github.com/hajimehoshi/ebiten/v2/inpututil"
|
||||||
|
)
|
||||||
|
|
||||||
|
// Dir represents a direction.
|
||||||
|
type Dir int
|
||||||
|
|
||||||
|
// represents the valid directions
|
||||||
|
const (
|
||||||
|
DirUp Dir = iota
|
||||||
|
DirRight
|
||||||
|
DirDown
|
||||||
|
DirLeft
|
||||||
|
)
|
||||||
|
|
||||||
|
type mouseState int
|
||||||
|
|
||||||
|
const (
|
||||||
|
mouseStateNone mouseState = iota
|
||||||
|
mouseStatePressing
|
||||||
|
mouseStateSettled
|
||||||
|
)
|
||||||
|
|
||||||
|
type touchState int
|
||||||
|
|
||||||
|
const (
|
||||||
|
touchStateNone touchState = iota
|
||||||
|
touchStatePressing
|
||||||
|
touchStateSettled
|
||||||
|
touchStateInvalid
|
||||||
|
)
|
||||||
|
|
||||||
|
// String returns a string representing the direction.
|
||||||
|
func (d Dir) String() string {
|
||||||
|
switch d {
|
||||||
|
case DirUp:
|
||||||
|
return "Up"
|
||||||
|
case DirRight:
|
||||||
|
return "Right"
|
||||||
|
case DirDown:
|
||||||
|
return "Down"
|
||||||
|
case DirLeft:
|
||||||
|
return "Left"
|
||||||
|
}
|
||||||
|
panic("not reach")
|
||||||
|
}
|
||||||
|
|
||||||
|
// Vector returns a [-1, 1] value for each axis.
|
||||||
|
func (d Dir) Vector() (x, y int) {
|
||||||
|
switch d {
|
||||||
|
case DirUp:
|
||||||
|
return 0, -1
|
||||||
|
case DirRight:
|
||||||
|
return 1, 0
|
||||||
|
case DirDown:
|
||||||
|
return 0, 1
|
||||||
|
case DirLeft:
|
||||||
|
return -1, 0
|
||||||
|
}
|
||||||
|
panic("not reach")
|
||||||
|
}
|
||||||
|
|
||||||
|
// Input represents the current key states.
|
||||||
|
type Input struct {
|
||||||
|
mouseState mouseState
|
||||||
|
mouseInitPosX int
|
||||||
|
mouseInitPosY int
|
||||||
|
mouseDir Dir
|
||||||
|
|
||||||
|
touches []ebiten.TouchID
|
||||||
|
touchState touchState
|
||||||
|
touchID ebiten.TouchID
|
||||||
|
touchInitPosX int
|
||||||
|
touchInitPosY int
|
||||||
|
touchLastPosX int
|
||||||
|
touchLastPosY int
|
||||||
|
touchDir Dir
|
||||||
|
}
|
||||||
|
|
||||||
|
// NewInput generates a new Input object.
|
||||||
|
func NewInput() *Input {
|
||||||
|
return &Input{}
|
||||||
|
}
|
||||||
|
|
||||||
|
func abs(x int) int {
|
||||||
|
if x < 0 {
|
||||||
|
return -x
|
||||||
|
}
|
||||||
|
return x
|
||||||
|
}
|
||||||
|
|
||||||
|
func vecToDir(dx, dy int) (Dir, bool) {
|
||||||
|
if abs(dx) < 4 && abs(dy) < 4 {
|
||||||
|
return 0, false
|
||||||
|
}
|
||||||
|
if abs(dx) < abs(dy) {
|
||||||
|
if dy < 0 {
|
||||||
|
return DirUp, true
|
||||||
|
}
|
||||||
|
return DirDown, true
|
||||||
|
}
|
||||||
|
if dx < 0 {
|
||||||
|
return DirLeft, true
|
||||||
|
}
|
||||||
|
return DirRight, true
|
||||||
|
}
|
||||||
|
|
||||||
|
// Update updates the current input states.
|
||||||
|
func (i *Input) Update() {
|
||||||
|
switch i.mouseState {
|
||||||
|
case mouseStateNone:
|
||||||
|
if ebiten.IsMouseButtonPressed(ebiten.MouseButtonLeft) {
|
||||||
|
x, y := ebiten.CursorPosition()
|
||||||
|
i.mouseInitPosX = x
|
||||||
|
i.mouseInitPosY = y
|
||||||
|
i.mouseState = mouseStatePressing
|
||||||
|
}
|
||||||
|
case mouseStatePressing:
|
||||||
|
if !ebiten.IsMouseButtonPressed(ebiten.MouseButtonLeft) {
|
||||||
|
x, y := ebiten.CursorPosition()
|
||||||
|
dx := x - i.mouseInitPosX
|
||||||
|
dy := y - i.mouseInitPosY
|
||||||
|
d, ok := vecToDir(dx, dy)
|
||||||
|
if !ok {
|
||||||
|
i.mouseState = mouseStateNone
|
||||||
|
break
|
||||||
|
}
|
||||||
|
i.mouseDir = d
|
||||||
|
i.mouseState = mouseStateSettled
|
||||||
|
}
|
||||||
|
case mouseStateSettled:
|
||||||
|
i.mouseState = mouseStateNone
|
||||||
|
}
|
||||||
|
|
||||||
|
i.touches = ebiten.AppendTouchIDs(i.touches[:0])
|
||||||
|
switch i.touchState {
|
||||||
|
case touchStateNone:
|
||||||
|
if len(i.touches) == 1 {
|
||||||
|
i.touchID = i.touches[0]
|
||||||
|
x, y := ebiten.TouchPosition(i.touches[0])
|
||||||
|
i.touchInitPosX = x
|
||||||
|
i.touchInitPosY = y
|
||||||
|
i.touchLastPosX = x
|
||||||
|
i.touchLastPosX = y
|
||||||
|
i.touchState = touchStatePressing
|
||||||
|
}
|
||||||
|
case touchStatePressing:
|
||||||
|
if len(i.touches) >= 2 {
|
||||||
|
break
|
||||||
|
}
|
||||||
|
if len(i.touches) == 1 {
|
||||||
|
if i.touches[0] != i.touchID {
|
||||||
|
i.touchState = touchStateInvalid
|
||||||
|
} else {
|
||||||
|
x, y := ebiten.TouchPosition(i.touches[0])
|
||||||
|
i.touchLastPosX = x
|
||||||
|
i.touchLastPosY = y
|
||||||
|
}
|
||||||
|
break
|
||||||
|
}
|
||||||
|
if len(i.touches) == 0 {
|
||||||
|
dx := i.touchLastPosX - i.touchInitPosX
|
||||||
|
dy := i.touchLastPosY - i.touchInitPosY
|
||||||
|
d, ok := vecToDir(dx, dy)
|
||||||
|
if !ok {
|
||||||
|
i.touchState = touchStateNone
|
||||||
|
break
|
||||||
|
}
|
||||||
|
i.touchDir = d
|
||||||
|
i.touchState = touchStateSettled
|
||||||
|
}
|
||||||
|
case touchStateSettled:
|
||||||
|
i.touchState = touchStateNone
|
||||||
|
case touchStateInvalid:
|
||||||
|
if len(i.touches) == 0 {
|
||||||
|
i.touchState = touchStateNone
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// Dir returns a currently pressed direction.
|
||||||
|
// Dir returns false if no direction key is pressed.
|
||||||
|
func (i *Input) Dir() (Dir, bool) {
|
||||||
|
if inpututil.IsKeyJustPressed(ebiten.KeyArrowUp) {
|
||||||
|
return DirUp, true
|
||||||
|
}
|
||||||
|
if inpututil.IsKeyJustPressed(ebiten.KeyArrowLeft) {
|
||||||
|
return DirLeft, true
|
||||||
|
}
|
||||||
|
if inpututil.IsKeyJustPressed(ebiten.KeyArrowRight) {
|
||||||
|
return DirRight, true
|
||||||
|
}
|
||||||
|
if inpututil.IsKeyJustPressed(ebiten.KeyArrowDown) {
|
||||||
|
return DirDown, true
|
||||||
|
}
|
||||||
|
if i.mouseState == mouseStateSettled {
|
||||||
|
return i.mouseDir, true
|
||||||
|
}
|
||||||
|
if i.touchState == touchStateSettled {
|
||||||
|
return i.touchDir, true
|
||||||
|
}
|
||||||
|
return 0, false
|
||||||
|
}
|
120
main.go
120
main.go
@ -1,16 +1,128 @@
|
|||||||
package main
|
package main
|
||||||
|
|
||||||
import "fmt"
|
import (
|
||||||
|
"errors"
|
||||||
|
"fmt"
|
||||||
|
"log"
|
||||||
|
"time"
|
||||||
|
|
||||||
|
"github.com/hajimehoshi/ebiten/v2"
|
||||||
|
)
|
||||||
|
|
||||||
|
func dummyGame() (*Game, error) {
|
||||||
|
g := &Game{
|
||||||
|
board: NewBoard(4),
|
||||||
|
state: gameSetup,
|
||||||
|
}
|
||||||
|
//Setup terrain
|
||||||
|
terrain := []struct {
|
||||||
|
x, y, t int
|
||||||
|
}{
|
||||||
|
{1, 1, 1},
|
||||||
|
{2, 2, 1},
|
||||||
|
}
|
||||||
|
for _, tt := range terrain {
|
||||||
|
res, err := g.board.AddTerrain(tt.x, tt.y, tt.t)
|
||||||
|
if err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
if !res {
|
||||||
|
return nil, errors.New("Error creating terrain")
|
||||||
|
}
|
||||||
|
}
|
||||||
|
pieces := []struct {
|
||||||
|
x, y int
|
||||||
|
p *Piece
|
||||||
|
}{
|
||||||
|
{0, 0, NewPiece(Flag, Blue)},
|
||||||
|
{3, 0, NewPiece(Spy, Blue)},
|
||||||
|
{2, 0, NewPiece(Captain, Blue)},
|
||||||
|
{3, 1, NewPiece(Marshal, Blue)},
|
||||||
|
{0, 1, NewPiece(Bomb, Blue)},
|
||||||
|
|
||||||
|
{1, 2, NewPiece(Flag, Red)},
|
||||||
|
{3, 2, NewPiece(Spy, Red)},
|
||||||
|
{2, 3, NewPiece(Captain, Red)},
|
||||||
|
{0, 2, NewPiece(Marshal, Red)},
|
||||||
|
{0, 3, NewPiece(Bomb, Red)},
|
||||||
|
}
|
||||||
|
for _, tt := range pieces {
|
||||||
|
res, err := g.SetupPiece(tt.x, tt.y, tt.p)
|
||||||
|
if err != nil {
|
||||||
|
return nil, fmt.Errorf("Piece %v,%v:%v", tt.x, tt.y, err)
|
||||||
|
}
|
||||||
|
if !res {
|
||||||
|
return nil, errors.New("error placing dummy piece")
|
||||||
|
}
|
||||||
|
}
|
||||||
|
_, err := g.SetupPiece(0, 0, NewPiece(Flag, Blue))
|
||||||
|
if err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
|
||||||
|
return g, nil
|
||||||
|
}
|
||||||
func main() {
|
func main() {
|
||||||
//red := NewDummyPlayer(Red)
|
//red := NewDummyPlayer(Red)
|
||||||
//blue := NewDummyPlayer(Blue)
|
//blue := NewDummyPlayer(Blue)
|
||||||
g := NewGame()
|
g, err := dummyGame()
|
||||||
g.state = gameSetup
|
if err != nil {
|
||||||
printboardcolours(g)
|
panic(err)
|
||||||
|
}
|
||||||
|
go func(g *Game) {
|
||||||
|
r := NewDummyPlayer(Red)
|
||||||
|
b := NewDummyPlayer(Blue)
|
||||||
|
g.Start()
|
||||||
|
var moves = []struct {
|
||||||
|
input string
|
||||||
|
player Player
|
||||||
|
res bool
|
||||||
|
}{
|
||||||
|
{"c3-b3", r, true},
|
||||||
|
{"c0-c1", b, true},
|
||||||
|
{"d2xd1", r, true},
|
||||||
|
{"c1-d1", b, true},
|
||||||
|
{"b3-c3", r, true},
|
||||||
|
{"d1xd2", b, true},
|
||||||
|
}
|
||||||
|
for i, tt := range moves {
|
||||||
|
time.Sleep(3 * time.Second)
|
||||||
|
log.Printf("playing move %v\n", i)
|
||||||
|
raw, err := NewRawCommand(tt.input)
|
||||||
|
if err != nil {
|
||||||
|
panic(err)
|
||||||
|
}
|
||||||
|
parsed, err := g.Parse(tt.player, raw)
|
||||||
|
if err != nil {
|
||||||
|
panic(err)
|
||||||
|
}
|
||||||
|
res, err := g.Mutate(parsed)
|
||||||
|
if err != nil {
|
||||||
|
panic(err)
|
||||||
|
}
|
||||||
|
if res {
|
||||||
|
log.Printf("move %v successful\n", i)
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
}(g)
|
||||||
|
viewer(g)
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func viewer(g *Game) {
|
||||||
|
v, err := NewViewer(g)
|
||||||
|
if err != nil {
|
||||||
|
panic(err)
|
||||||
|
}
|
||||||
|
ebiten.SetWindowSize(800, 640)
|
||||||
|
ebiten.SetWindowTitle("Freego")
|
||||||
|
if err := ebiten.RunGame(v); err != nil {
|
||||||
|
panic(err)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
func addpiece(game *Game, rank int, c Colour, x int, y int) {
|
func addpiece(game *Game, rank int, c Colour, x int, y int) {
|
||||||
res, err := game.SetupPiece(x, y, NewPieceFromInt(rank, c))
|
res, err := game.SetupPiece(x, y, NewPieceFromInt(rank, c))
|
||||||
if err != nil {
|
if err != nil {
|
||||||
|
91
view_board.go
Normal file
91
view_board.go
Normal file
@ -0,0 +1,91 @@
|
|||||||
|
package main
|
||||||
|
|
||||||
|
import (
|
||||||
|
"errors"
|
||||||
|
"image/color"
|
||||||
|
"log"
|
||||||
|
|
||||||
|
"github.com/hajimehoshi/ebiten/v2"
|
||||||
|
)
|
||||||
|
|
||||||
|
var errorTaskTerminated = errors.New("freego: task terminated")
|
||||||
|
|
||||||
|
type task func() error
|
||||||
|
|
||||||
|
// ViewBoard represents the game board.
|
||||||
|
type ViewBoard struct {
|
||||||
|
size int
|
||||||
|
tiles map[*ViewTile]struct{}
|
||||||
|
tasks []task
|
||||||
|
}
|
||||||
|
|
||||||
|
// NewViewBoard generates a new ViewBoard with giving a size.
|
||||||
|
func NewViewBoard(g *Game) (*ViewBoard, error) {
|
||||||
|
size := g.board.size
|
||||||
|
b := &ViewBoard{
|
||||||
|
size: size,
|
||||||
|
tiles: map[*ViewTile]struct{}{},
|
||||||
|
}
|
||||||
|
for i := 0; i < size; i++ {
|
||||||
|
for j := 0; j < size; j++ {
|
||||||
|
b.tiles[NewViewTile(i, j, g.board.board[i][j])] = struct{}{}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return b, nil
|
||||||
|
}
|
||||||
|
|
||||||
|
//func (b *ViewBoard) tileAt(x, y int) *Tile {
|
||||||
|
// return tileAt(b.tiles, x, y)
|
||||||
|
//}
|
||||||
|
|
||||||
|
// Update updates the board state.
|
||||||
|
func (b *ViewBoard) Update(input *Input) error {
|
||||||
|
for t := range b.tiles {
|
||||||
|
if err := t.Update(); err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if 0 < len(b.tasks) {
|
||||||
|
t := b.tasks[0]
|
||||||
|
if err := t(); err == errorTaskTerminated {
|
||||||
|
b.tasks = b.tasks[1:]
|
||||||
|
} else if err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
if dir, ok := input.Dir(); ok {
|
||||||
|
//if err := b.Move(dir); err != nil {
|
||||||
|
// return err
|
||||||
|
//}
|
||||||
|
log.Println(dir)
|
||||||
|
}
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
|
||||||
|
// Draw draws the board to the given boardImage.
|
||||||
|
func (b *ViewBoard) Draw(boardImage *ebiten.Image) {
|
||||||
|
boardImage.Fill(color.RGBA{0xbb, 0xad, 0xa0, 0xff})
|
||||||
|
for j := 0; j < b.size; j++ {
|
||||||
|
for i := 0; i < b.size; i++ {
|
||||||
|
//v := 0
|
||||||
|
op := &ebiten.DrawImageOptions{}
|
||||||
|
x := i*tileSize + (i+1)*tileMargin
|
||||||
|
y := j*tileSize + (j+1)*tileMargin
|
||||||
|
op.GeoM.Translate(float64(x), float64(y))
|
||||||
|
//op.ColorM.ScaleWithColor(tileBackgroundColor(v))
|
||||||
|
boardImage.DrawImage(tileImage, op)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
for t := range b.tiles {
|
||||||
|
t.Draw(boardImage)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// Size returns the board size.
|
||||||
|
func (b *ViewBoard) Size() (int, int) {
|
||||||
|
x := b.size*tileSize + (b.size+1)*tileMargin
|
||||||
|
y := x
|
||||||
|
return x, y
|
||||||
|
}
|
129
view_tile.go
Normal file
129
view_tile.go
Normal file
@ -0,0 +1,129 @@
|
|||||||
|
package main
|
||||||
|
|
||||||
|
import (
|
||||||
|
"image/color"
|
||||||
|
"log"
|
||||||
|
|
||||||
|
"github.com/hajimehoshi/ebiten/examples/resources/fonts"
|
||||||
|
"github.com/hajimehoshi/ebiten/v2"
|
||||||
|
"github.com/hajimehoshi/ebiten/v2/text"
|
||||||
|
"golang.org/x/image/font"
|
||||||
|
"golang.org/x/image/font/opentype"
|
||||||
|
)
|
||||||
|
|
||||||
|
//ViewTile is a tile in the viewer
|
||||||
|
type ViewTile struct {
|
||||||
|
gameTile *Tile
|
||||||
|
|
||||||
|
// next represents a next tile information after moving.
|
||||||
|
// next is empty when the tile is not about to move.
|
||||||
|
//next TileData
|
||||||
|
|
||||||
|
//movingCount int
|
||||||
|
//startPoppingCount int
|
||||||
|
//poppingCount int
|
||||||
|
}
|
||||||
|
|
||||||
|
var (
|
||||||
|
tileImage = ebiten.NewImage(tileSize, tileSize)
|
||||||
|
)
|
||||||
|
|
||||||
|
var (
|
||||||
|
mplusSmallFont font.Face
|
||||||
|
mplusNormalFont font.Face
|
||||||
|
mplusBigFont font.Face
|
||||||
|
)
|
||||||
|
|
||||||
|
const (
|
||||||
|
tileSize = 80
|
||||||
|
tileMargin = 4
|
||||||
|
)
|
||||||
|
|
||||||
|
func init() {
|
||||||
|
tt, err := opentype.Parse(fonts.MPlus1pRegular_ttf)
|
||||||
|
if err != nil {
|
||||||
|
log.Fatal(err)
|
||||||
|
}
|
||||||
|
|
||||||
|
const dpi = 72
|
||||||
|
mplusSmallFont, err = opentype.NewFace(tt, &opentype.FaceOptions{
|
||||||
|
Size: 24,
|
||||||
|
DPI: dpi,
|
||||||
|
Hinting: font.HintingFull,
|
||||||
|
})
|
||||||
|
if err != nil {
|
||||||
|
log.Fatal(err)
|
||||||
|
}
|
||||||
|
mplusNormalFont, err = opentype.NewFace(tt, &opentype.FaceOptions{
|
||||||
|
Size: 32,
|
||||||
|
DPI: dpi,
|
||||||
|
Hinting: font.HintingFull,
|
||||||
|
})
|
||||||
|
if err != nil {
|
||||||
|
log.Fatal(err)
|
||||||
|
}
|
||||||
|
mplusBigFont, err = opentype.NewFace(tt, &opentype.FaceOptions{
|
||||||
|
Size: 48,
|
||||||
|
DPI: dpi,
|
||||||
|
Hinting: font.HintingFull,
|
||||||
|
})
|
||||||
|
if err != nil {
|
||||||
|
log.Fatal(err)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
//NewViewTile creates a new view tile
|
||||||
|
func NewViewTile(x, y int, t *Tile) *ViewTile {
|
||||||
|
return &ViewTile{
|
||||||
|
gameTile: t,
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// Update updates the tile's animation states.
|
||||||
|
func (t *ViewTile) Update() error {
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
|
||||||
|
// Draw draws the current tile to the given boardImage.
|
||||||
|
func (t *ViewTile) Draw(boardImage *ebiten.Image) {
|
||||||
|
j, i := t.gameTile.x, t.gameTile.y
|
||||||
|
v := t.gameTile.entity
|
||||||
|
if v == nil && t.gameTile.Passable() {
|
||||||
|
return
|
||||||
|
}
|
||||||
|
op := &ebiten.DrawImageOptions{}
|
||||||
|
x := i*tileSize + (i+1)*tileMargin
|
||||||
|
y := j*tileSize + (j+1)*tileMargin
|
||||||
|
op.GeoM.Translate(float64(x), float64(y))
|
||||||
|
//op.ColorM.ScaleWithColor(tileBackgroundColor(v))
|
||||||
|
boardImage.DrawImage(tileImage, op)
|
||||||
|
str := "NA"
|
||||||
|
if v == nil {
|
||||||
|
str = "river"
|
||||||
|
} else {
|
||||||
|
str = v.Rank.String()
|
||||||
|
}
|
||||||
|
|
||||||
|
f := mplusBigFont
|
||||||
|
switch {
|
||||||
|
case 3 < len(str):
|
||||||
|
f = mplusSmallFont
|
||||||
|
case 2 < len(str):
|
||||||
|
f = mplusNormalFont
|
||||||
|
}
|
||||||
|
|
||||||
|
bound, _ := font.BoundString(f, str)
|
||||||
|
w := (bound.Max.X - bound.Min.X).Ceil()
|
||||||
|
h := (bound.Max.Y - bound.Min.Y).Ceil()
|
||||||
|
x = x + (tileSize-w)/2
|
||||||
|
y = y + (tileSize-h)/2 + h
|
||||||
|
pieceColor := color.RGBA{0xf9, 0xf6, 0xf2, 0xff}
|
||||||
|
if v != nil {
|
||||||
|
if t.gameTile.entity.Owner == Red {
|
||||||
|
pieceColor = color.RGBA{0xff, 0x0, 0x0, 0xff}
|
||||||
|
} else if t.gameTile.entity.Owner == Blue {
|
||||||
|
pieceColor = color.RGBA{0x0, 0x0, 0xff, 0xff}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
text.Draw(boardImage, str, f, x, y, pieceColor)
|
||||||
|
}
|
60
viewer.go
Normal file
60
viewer.go
Normal file
@ -0,0 +1,60 @@
|
|||||||
|
package main
|
||||||
|
|
||||||
|
import (
|
||||||
|
"image/color"
|
||||||
|
|
||||||
|
"github.com/hajimehoshi/ebiten/v2"
|
||||||
|
)
|
||||||
|
|
||||||
|
//Viewer is a graphical representation of a freego game
|
||||||
|
type Viewer struct {
|
||||||
|
input *Input
|
||||||
|
board *ViewBoard
|
||||||
|
boardImage *ebiten.Image
|
||||||
|
gameState *Game
|
||||||
|
}
|
||||||
|
|
||||||
|
//NewViewer creates a new viewer
|
||||||
|
func NewViewer(g *Game) (*Viewer, error) {
|
||||||
|
v := &Viewer{
|
||||||
|
input: NewInput(),
|
||||||
|
gameState: g,
|
||||||
|
}
|
||||||
|
var err error
|
||||||
|
v.board, err = NewViewBoard(g)
|
||||||
|
if err != nil {
|
||||||
|
panic(err)
|
||||||
|
}
|
||||||
|
return v, nil
|
||||||
|
}
|
||||||
|
|
||||||
|
// Layout implements ebiten.Game's Layout.
|
||||||
|
func (v *Viewer) Layout(outsideWidth, outsideHeight int) (screenWidth, screenHeight int) {
|
||||||
|
return 800, 640
|
||||||
|
}
|
||||||
|
|
||||||
|
// Update updates the current game state.
|
||||||
|
func (v *Viewer) Update() error {
|
||||||
|
v.input.Update()
|
||||||
|
if err := v.board.Update(v.input); err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
|
||||||
|
// Draw draws the current game to the given screen.
|
||||||
|
func (v *Viewer) Draw(screen *ebiten.Image) {
|
||||||
|
if v.boardImage == nil {
|
||||||
|
w, h := v.board.Size()
|
||||||
|
v.boardImage = ebiten.NewImage(w, h)
|
||||||
|
}
|
||||||
|
screen.Fill(color.RGBA{0xfa, 0xf8, 0xef, 0xff})
|
||||||
|
v.board.Draw(v.boardImage)
|
||||||
|
op := &ebiten.DrawImageOptions{}
|
||||||
|
sw, sh := screen.Size()
|
||||||
|
bw, bh := v.boardImage.Size()
|
||||||
|
x := (sw - bw) / 2
|
||||||
|
y := (sh - bh) / 2
|
||||||
|
op.GeoM.Translate(float64(x), float64(y))
|
||||||
|
screen.DrawImage(v.boardImage, op)
|
||||||
|
}
|
Loading…
Reference in New Issue
Block a user