DelayNoMore/collider_visualizer/main.go

170 lines
4.3 KiB
Go
Raw Normal View History

package main
import (
_ "embed"
"fmt"
"image/color"
"go.uber.org/zap"
"github.com/golang/freetype/truetype"
"github.com/hajimehoshi/ebiten/v2"
"github.com/hajimehoshi/ebiten/v2/ebitenutil"
"github.com/hajimehoshi/ebiten/v2/text"
"github.com/solarlune/resolv"
"golang.org/x/image/font"
"encoding/xml"
"io/ioutil"
"os"
"path/filepath"
. "dnmshared"
)
func parseStage(stageName string) (int32, int32, int32, int32, StrToVec2DListMap, StrToPolygon2DListMap, error) {
pwd, err := os.Getwd()
if nil != err {
Logger.Error("Failed to get current working dir:", zap.Any("pwd", pwd), zap.Any("err", err))
}
relativePathForAllStages := "../frontend/assets/resources/map"
relativePathForChosenStage := fmt.Sprintf("%s/%s", relativePathForAllStages, stageName)
pTmxMapIns := &TmxMap{}
absDirPathContainingDirectlyTmxFile := filepath.Join(pwd, relativePathForChosenStage)
absTmxFilePath := fmt.Sprintf("%s/map.tmx", absDirPathContainingDirectlyTmxFile)
if !filepath.IsAbs(absTmxFilePath) {
panic("Tmx filepath must be absolute!")
}
byteArr, err := ioutil.ReadFile(absTmxFilePath)
if nil != err {
panic(err)
}
err = xml.Unmarshal(byteArr, pTmxMapIns)
if nil != err {
panic(err)
}
// Obtain the content of `gidBoundariesMapInB2World`.
gidBoundariesMapInB2World := make(map[int]StrToPolygon2DListMap, 0)
for _, tileset := range pTmxMapIns.Tilesets {
relativeTsxFilePath := fmt.Sprintf("%s/%s", filepath.Join(pwd, relativePathForChosenStage), tileset.Source) // Note that "TmxTileset.Source" can be a string of "relative path".
absTsxFilePath, err := filepath.Abs(relativeTsxFilePath)
if nil != err {
panic(err)
}
if !filepath.IsAbs(absTsxFilePath) {
panic("Filepath must be absolute!")
}
byteArrOfTsxFile, err := ioutil.ReadFile(absTsxFilePath)
if nil != err {
panic(err)
}
DeserializeTsxToColliderDict(pTmxMapIns, byteArrOfTsxFile, int(tileset.FirstGid), gidBoundariesMapInB2World)
}
return ParseTmxLayersAndGroups(pTmxMapIns, gidBoundariesMapInB2World)
}
//go:embed excel.ttf
var excelFont []byte
type Game struct {
World WorldInterface
Width, Height int
Debug bool
ShowHelpText bool
Screen *ebiten.Image
FontFace font.Face
}
func NewGame() *Game {
stageDiscreteW, stageDiscreteH, stageTileW, stageTileH, playerPosMap, barrierMap, err := parseStage("richsoil")
if nil != err {
panic(err)
}
spaceW := stageDiscreteW * stageTileW
spaceH := stageDiscreteH * stageTileH
ebiten.SetWindowResizable(true)
ebiten.SetWindowTitle("resolv test")
g := &Game{
Width: int(spaceW),
Height: int(spaceH),
ShowHelpText: true,
}
g.World = NewWorldColliderDisplay(g, stageDiscreteW, stageDiscreteH, stageTileW, stageTileH, playerPosMap, barrierMap)
fontData, _ := truetype.Parse(excelFont)
g.FontFace = truetype.NewFace(fontData, &truetype.Options{Size: 10})
return g
}
func (g *Game) Update() error {
g.World.Update()
return nil
}
func (g *Game) Draw(screen *ebiten.Image) {
g.Screen = screen
screen.Fill(color.RGBA{20, 20, 40, 255})
g.World.Draw(screen)
}
func (g *Game) DrawText(screen *ebiten.Image, x, y int, textLines ...string) {
rectHeight := 10
for _, txt := range textLines {
w := float64(font.MeasureString(g.FontFace, txt).Round())
ebitenutil.DrawRect(screen, float64(x), float64(y-8), w, float64(rectHeight), color.RGBA{0, 0, 0, 192})
text.Draw(screen, txt, g.FontFace, x+1, y+1, color.RGBA{0, 0, 150, 255})
text.Draw(screen, txt, g.FontFace, x, y, color.RGBA{100, 150, 255, 255})
y += rectHeight
}
}
func (g *Game) DebugDraw(screen *ebiten.Image, space *resolv.Space) {
for y := 0; y < space.Height(); y++ {
for x := 0; x < space.Width(); x++ {
cell := space.Cell(x, y)
cw := float64(space.CellWidth)
ch := float64(space.CellHeight)
cx := float64(cell.X) * cw
cy := float64(cell.Y) * ch
drawColor := color.RGBA{20, 20, 20, 255}
if cell.Occupied() {
drawColor = color.RGBA{255, 255, 0, 255}
}
ebitenutil.DrawLine(screen, cx, cy, cx+cw, cy, drawColor)
ebitenutil.DrawLine(screen, cx+cw, cy, cx+cw, cy+ch, drawColor)
ebitenutil.DrawLine(screen, cx+cw, cy+ch, cx, cy+ch, drawColor)
ebitenutil.DrawLine(screen, cx, cy+ch, cx, cy, drawColor)
}
}
}
func (g *Game) Layout(w, h int) (int, int) {
return g.Width, g.Height
}
func main() {
ebiten.RunGame(NewGame())
}