2022-10-14 08:08:22 +00:00
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"
"golang.org/x/image/font"
"encoding/xml"
"io/ioutil"
"os"
"path/filepath"
2022-12-26 12:37:40 +00:00
"resolv"
2022-10-14 08:08:22 +00:00
. "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 {
2022-11-16 14:11:56 +00:00
// stageName := "simple" // Use this for calibration in isometric orientation
2022-10-19 00:32:20 +00:00
// stageName := "richsoil"
2022-11-16 12:58:12 +00:00
stageName := "dungeon"
2022-10-14 16:35:32 +00:00
stageDiscreteW , stageDiscreteH , stageTileW , stageTileH , playerPosMap , barrierMap , err := parseStage ( stageName )
2022-10-14 10:02:03 +00:00
if nil != err {
panic ( err )
}
2022-10-15 08:51:38 +00:00
PolygonFillerImage . Fill ( color . RGBA { 60 , 60 , 60 , 255 } ) // Required to init color of the polygons!
2022-10-14 10:02:03 +00:00
spaceW := stageDiscreteW * stageTileW
spaceH := stageDiscreteH * stageTileH
2022-10-14 08:08:22 +00:00
ebiten . SetWindowResizable ( true )
ebiten . SetWindowTitle ( "resolv test" )
g := & Game {
2022-10-14 10:02:03 +00:00
Width : int ( spaceW ) ,
Height : int ( spaceH ) ,
2022-10-14 08:08:22 +00:00
ShowHelpText : true ,
}
2022-10-14 10:02:03 +00:00
g . World = NewWorldColliderDisplay ( g , stageDiscreteW , stageDiscreteH , stageTileW , stageTileH , playerPosMap , barrierMap )
2022-10-14 08:08:22 +00:00
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 ( ) )
}