package assetstore import ( "image" "log" "code.ur.gs/lupine/ordoor/internal/maps" ) type Map struct { assets *AssetStore set *Set Rect image.Rectangle raw *maps.GameMap } // Map loads a game map with the given name (e.g. "Chapter01") func (a *AssetStore) Map(name string) (*Map, error) { name = canonical(name) if m, ok := a.maps[name]; ok { return m, nil } log.Printf("Loading map %v", name) mapFile, err := a.lookup(name, "map", "Maps", "MultiMaps") if err != nil { return nil, err } txtFile, err := a.lookup(name, "txt", "Maps", "MultiMaps") if err != nil { return nil, err } raw, err := maps.LoadGameMapByFiles(mapFile, txtFile) if err != nil { return nil, err } // The set for a map is small and frequently referenced, so load it here set, err := a.Set(raw.MapSetName()) if err != nil { return nil, err } m := &Map{ Rect: image.Rect( int(raw.MinWidth), int(raw.MinLength), int(raw.MaxWidth), int(raw.MaxLength), ), assets: a, raw: raw, set: set, } a.maps[canonical(name)] = m return m, nil } func (m *Map) LoadSprites() error { // Eager load the sprites we use for x := m.Rect.Min.X; x <= m.Rect.Max.X; x++ { for y := m.Rect.Min.Y; y <= m.Rect.Max.Y; y++ { for z := 0; z < maps.MaxHeight; z++ { if _, err := m.SpritesForCell(x, y, z); err != nil { return err } } } } return nil } // FIXME: get rid of this func (m *Map) Cell(x, y, z int) maps.Cell { return m.raw.Cells.At(x, y, z) } // SpritesForCell returns the sprites needed to correctly render this cell. // They should be rendered from first to last to get the correct ordering func (m *Map) SpritesForCell(x, y, z int) ([]*Sprite, error) { cell := m.raw.At(x, y, z) sprites := make([]*Sprite, 0, 4) for _, ref := range []maps.ObjRef{cell.Surface, cell.Right, cell.Left, cell.Center} { if !ref.IsActive() { continue } obj, err := m.set.Object(ref.Index()) if err != nil { return nil, err } sprite, err := obj.Sprite(ref.Sprite()) if err != nil { return nil, err } sprites = append(sprites, sprite) } return sprites, nil }