package dungeon import ( "bytes" "compress/zlib" "encoding/binary" "image" "image/draw" "image/png" "io" "unsafe" ) type TileType uint8 const ( TileTypeNone TileType = iota TileTypeFloor TileTypeWall ) type TileMap struct { Width int Height int Tiles []TileType } func NewTileMap(width, height int) TileMap { return TileMap{ Width: width, Height: height, Tiles: make([]TileType, width*height), } } func (t *TileMap) Get(x int, y int) TileType { return t.Tiles[y*t.Width+x] } func (t *TileMap) Set(x int, y int, tile TileType) { t.Tiles[y*t.Width+x] = tile } func (t *TileMap) Draw(tileSet *TileSet) *image.RGBA { tileMapImage := image.NewRGBA(image.Rect(0, 0, t.Width*tileSize, t.Height*tileSize)) for x := range t.Width { for y := range t.Height { tileType := t.Get(x, y) if tileType > 0 { tileRect := tileSet.TileBounds(tileType) draw.Draw(tileMapImage, image.Rect(x*tileSize, y*tileSize, (x*tileSize)+tileSize, (y*tileSize)+tileSize), tileSet.Image, image.Point{X: tileRect.Min.X, Y: tileRect.Min.Y}, draw.Src) } } } return tileMapImage } func (t *TileMap) ExportPNG(tileSet *TileSet, w io.Writer) error { return png.Encode(w, t.Draw(tileSet)) } func (t *TileMap) ExportBytes(w io.Writer) { header := make([]byte, 4) binary.LittleEndian.PutUint16(header, uint16(t.Width)) binary.LittleEndian.PutUint16(header[2:], uint16(t.Height)) tileBytes := *(*[]byte)(unsafe.Pointer(&t.Tiles)) zw := zlib.NewWriter(w) defer zw.Close() zw.Write(append(header, tileBytes...)) } func TileMapFromBytes(compressedTileMapData []byte) TileMap { zr, err := zlib.NewReader(bytes.NewReader(compressedTileMapData)) if err != nil { return TileMap{} } defer zr.Close() tileMapData, err := io.ReadAll(zr) if err != nil { return TileMap{} } if len(tileMapData) < 4 { return TileMap{} } width := int(binary.LittleEndian.Uint16(tileMapData[0:2])) height := int(binary.LittleEndian.Uint16(tileMapData[2:4])) if len(tileMapData[4:]) != width*height { return TileMap{} } tiles := make([]TileType, width*height) for i, b := range tileMapData[4:] { tiles[i] = TileType(b) } return TileMap{ Width: width, Height: height, Tiles: tiles, } }