package entities import ( "encoding/json" "fmt" "os" "github.com/go-gl/mathgl/mgl64" "github.com/hajimehoshi/ebiten/v2/ebitenutil" ) const ( TileSize = 32.0 // Varje block ar 32x32 world units ) type World struct { Width, Height, Depth int Grid [][][]Entity PortalTrigger string // Håller reda på om vi ska byta rum } func NewWorld(w, h, d int) *World { grid := make([][][]Entity, w) for x := 0; x < w; x++ { grid[x] = make([][]Entity, h) for y := 0; y < h; y++ { grid[x][y] = make([]Entity, d) } } return &World{Width: w, Height: h, Depth: d, Grid: grid, PortalTrigger: ""} } func (w *World) GetEntityAt(x, y, z int) Entity { if x < 0 || x >= w.Width || y < 0 || y >= w.Height || z < 0 || z >= w.Depth { return nil } return w.Grid[x][y][z] } func (w *World) SetEntityAt(x, y, z int, e Entity) { if x < 0 || x >= w.Width || y < 0 || y >= w.Height || z < 0 || z >= w.Depth { return } w.Grid[x][y][z] = e if e != nil { e.SetPos(mgl64.Vec3{float64(x), float64(y), float64(z)}) } } // Convert absolute 3D position to Grid index func ToGridIndex(pos mgl64.Vec3) (int, int, int) { return int(pos[0]/TileSize), int(pos[1]/TileSize), int(pos[2]/TileSize) } type TiledLayer struct { Data []int `json:"data"` Height int `json:"height"` Name string `json:"name"` Width int `json:"width"` Type string `json:"type"` } type TiledMap struct { Height int `json:"height"` Width int `json:"width"` Layers []TiledLayer `json:"layers"` } type Portal struct { pos mgl64.Vec3 TargetMap string } func (p *Portal) Pos() mgl64.Vec3 { return p.pos } func (p *Portal) SetPos(pos mgl64.Vec3) { p.pos = pos } func (p *Portal) IsBlocking() bool { return false } func (p *Portal) IsMovable() bool { return false } func (p *Portal) Move(dx, dy, dz float64) {} func (p *Portal) Damage(amount int) {} func (p *Portal) Pickup() bool { return false } func (p *Portal) GetHealth() int { return 100 } func (p *Portal) DrawSide(screen interface{}, x, y float64) {} func (p *Portal) DrawTop(screen interface{}, x, y float64) {} // Ladda en värld från Tiled Export (.tmj) func LoadWorldFromTiled(tmjPath string) (*World, error) { fileData, err := os.ReadFile(tmjPath) if err != nil { return nil, fmt.Errorf("kunde inte lasa map %s: %v", tmjPath, err) } var tMap TiledMap if err := json.Unmarshal(fileData, &tMap); err != nil { return nil, err } w := NewWorld(tMap.Width, 10, tMap.Height) // 10 i djup(height y), tileHeight z = height i Json tile12, _, _ := ebitenutil.NewImageFromFile("assets/images/1 Tiles/Tile_12.png") tile02, _, _ := ebitenutil.NewImageFromFile("assets/images/1 Tiles/Tile_02.png") tile31, _, _ := ebitenutil.NewImageFromFile("assets/images/1 Tiles/Tile_31.png") for _, layer := range tMap.Layers { if layer.Type != "tilelayer" { continue } var yLevel int fmt.Sscanf(layer.Name, "Y%d", &yLevel) if yLevel < 0 || yLevel >= 10 { continue } for i, tileID := range layer.Data { if tileID == 0 { continue } x := i % layer.Width z := i / layer.Width var ent Entity if tileID == 3 { // Portal ID target := "room2" if tmjPath == "mapp-maker/room2.tmj" { target = "room1" } ent = &Portal{ TargetMap: target } } else { // Mark if yLevel < 9 { ent = &Tile{ SideImg: tile12, TopImg: tile12 } } else { ent = &Tile{ SideImg: tile02, TopImg: tile31 } } } w.SetEntityAt(x, yLevel, z, ent) } } return w, nil }package entities import ( "encoding/json" "fmt" "log" "os" "github.com/go-gl/mathgl/mgl64" "github.com/hajimehoshi/ebiten/v2" "github.com/hajimehoshi/ebiten/v2/ebitenutil" ) const ( TileSize = 32.0 // Varje block ar 32x32 world units ) type World struct { Width, Height, Depth int Grid [][][]Entity PortalTrigger string // Håller reda på om vi ska byta rum } func NewWorld(w, h, d int) *World { grid := make([][][]Entity, w) for x := 0; x < w; x++ { grid[x] = make([][]Entity, h) for y := 0; y < h; y++ { grid[x][y] = make([]Entity, d) } } return &World{Width: w, Height: h, Depth: d, Grid: grid, PortalTrigger: ""} } func (w *World) GetEntityAt(x, y, z int) Entity { if x < 0 || x >= w.Width || y < 0 || y >= w.Height || z < 0 || z >= w.Depth { return nil } return w.Grid[x][y][z] } func (w *World) SetEntityAt(x, y, z int, e Entity) { if x < 0 || x >= w.Width || y < 0 || y >= w.Height || z < 0 || z >= w.Depth { return } w.Grid[x][y][z] = e if e != nil { e.SetPos(mgl64.Vec3{float64(x), float64(y), float64(z)}) } } // Convert absolute 3D position to Grid index func ToGridIndex(pos mgl64.Vec3) (int, int, int) { return int(pos[0]), int(pos[1]), int(pos[2]) } type TiledLayer struct { Data []int `json:"data"` Height int `json:"height"` Name string `json:"name"` Width int `json:"width"` Type string `json:"type"` } type TiledMap struct { Height int `json:"height"` Width int `json:"width"` Layers []TiledLayer `json:"layers"` } type Portal struct { pos mgl64.Vec3 TargetMap string } func (p *Portal) Pos() mgl64.Vec3 { return p.pos } func (p *Portal) SetPos(pos mgl64.Vec3) { p.pos = pos } func (p *Portal) IsBlocking() bool { return false } func (p *Portal) IsMovable() bool { return false } func (p *Portal) Move(dx, dy, dz float64) {} func (p *Portal) Damage(amount int) {} func (p *Portal) Pickup() bool { return false } func (p *Portal) GetHealth() int { return 100 } func (p *Portal) DrawSide(screen interface{}, x, y float64) {} func (p *Portal) DrawTop(screen interface{}, x, y float64) {} // Ladda en värld från Tiled Export (.tmj) func LoadWorldFromTiled(tmjPath string) (*World, error) { fileData, err := os.ReadFile(tmjPath) if err != nil { return nil, fmt.Errorf("kunde inte lasa map %s: %v", tmjPath, err) } var tMap TiledMap if err := json.Unmarshal(fileData, &tMap); err != nil { return nil, err } w := NewWorld(tMap.Width, 10, tMap.Height) // 10 i djup(height y), tileHeight z = height i Json tile12, _, _ := ebitenutil.NewImageFromFile("assets/images/1 Tiles/Tile_12.png") tile02, _, _ := ebitenutil.NewImageFromFile("assets/images/1 Tiles/Tile_02.png") tile31, _, _ := ebitenutil.NewImageFromFile("assets/images/1 Tiles/Tile_31.png") for _, layer := range tMap.Layers { if layer.Type != "tilelayer" { continue } var yLevel int fmt.Sscanf(layer.Name, "Y%d", &yLevel) if yLevel < 0 || yLevel >= 10 { continue } for i, tileID := range layer.Data { if tileID == 0 { continue } x := i % layer.Width z := i / layer.Width var ent Entity if tileID == 3 { // Portal ID log.Println("Hittade portal vid", x, yLevel, z) target := "room2" if tmjPath == "mapp-maker/room2.tmj" { target = "room1" } ent = &Portal{ TargetMap: target } } else { // Mark if yLevel < 9 { ent = &Tile{ SideImg: tile12, TopImg: tile12 } } else { ent = &Tile{ SideImg: tile02, TopImg: tile31 } } } w.SetEntityAt(x, yLevel, z, ent) } } return w, nil }