package conv import ( "bytes" "image/color" "log" "github.com/faiface/pixel" "ur.gs/ordoor/internal/data" ) // Important conversions: // // * Width & height now stored using int // * Colour data is now 32-bit rather than using a palette type Sprite struct { Width int Height int Pic *pixel.PictureData } type Object struct { Name string Sprites []Sprite } func ConvertObject(rawObj *data.Object, name string) *Object { out := &Object{ Name: name, Sprites: make([]Sprite, len(rawObj.Sprites)), } for i, rawSpr := range rawObj.Sprites { out.Sprites[i] = Sprite{ Width: int(rawSpr.Width), Height: int(rawSpr.Height), Pic: spriteToPic(rawSpr), } } return out } var transparent = color.RGBA{0, 0, 0, 0} // WIP. Try to convert the pixeldata into a picture. func spriteToPic(sprite *data.Sprite) *pixel.PictureData { pic := pixel.MakePictureData(pixel.R(float64(0), float64(0), float64(sprite.Width), float64(sprite.Height))) buf := bytes.NewBuffer(sprite.PixelData) // The pixeldata seems to be formed of Y null-terminated records, with // varying numbers of bytes in each row. Probably [type, *data] but ignore // type for now. // // Theory: perhaps the data in each X is centered around the origin? for y := 0; y < int(sprite.Height); y++ { insn := buf.Next(1)[0] // Take the instruction byte, if that's what it is switch insn { case 0: log.Printf("Reached the end of the sprite at y=%v (height=%v)", y, sprite.Height) case 1, 0x80: // Ignore these, as we know they exist and the logic below seems to handle them // Although I suspect 0x80 means "centered run of bytes" while 0x1 // means "left-aligned run of bytes", since all 0x1 rows seem to be // for 1x1 images, it makes no practical difference default: log.Printf("Record of unknown type %v", insn) } rowData, err := buf.ReadBytes(0) if err != nil { log.Printf("Error at y=%d: %v", y, err) continue } // Ignore the record separator rowData = rowData[0 : len(rowData)-1] leftPad := (int(sprite.Width) - len(rowData)) / 2 // Set all bytes to be transparent by default for allX := 0; allX < int(sprite.Width); allX++ { idx := pic.Index(pixel.V(float64(allX), float64(y))) pic.Pix[idx] = transparent } for x, b := range rowData { idx := pic.Index(pixel.V(float64(leftPad+x), float64(y))) r, g, b, a := data.ColorPalette[int(b)].RGBA() pic.Pix[idx] = color.RGBA{uint8(r), uint8(g), uint8(b), uint8(a)} } } return pic }