package assetstore import ( "fmt" "image" "log" "code.ur.gs/lupine/ordoor/internal/data" "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: raw.Rect(), 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.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, fmt.Errorf("Failed to get object for %#+v: %v", ref, err) } sprite, err := obj.Sprite(ref.Sprite()) if err != nil { return nil, err } sprites = append(sprites, sprite) } if chr := m.CharacterAt(x, y, z); chr != nil { // Look up the correct animation, get the frame, boom shakalaka anim, err := m.assets.CharacterAnimation(chr.Type, data.AnimActionNone, int(chr.Orientation)) if err != nil { return nil, err } sprites = append(sprites, anim.Frames[0]) } return sprites, nil } func (m *Map) CharacterAt(x, y, z int) *maps.Character { // FIXME: don't iterate for i, _ := range m.raw.Characters { chr := &m.raw.Characters[i] if chr.XPos == x && chr.YPos == y && z == 0 { // FIXME: sort out ZPos return chr } } return nil }