-
Notifications
You must be signed in to change notification settings - Fork 0
/
generator.go
165 lines (117 loc) · 4.21 KB
/
generator.go
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
package engine
import (
"image"
"image/color"
_ "image/png"
"io/ioutil"
"log"
"math"
"os"
"strconv"
"strings"
)
// GenerateFromPNGFile generates a SpriteGroup package file from an image on disk
func GenerateFromPNGFile(inputFile string, outputFile string, packageName string, exportedSpriteName string, palettes ...Palette) {
imgFile, imgFileErr := os.Open(inputFile)
imgFileConfig, imgFileConfErr := os.Open(inputFile)
if imgFileErr != nil || imgFileConfErr != nil {
log.Fatal("Error reading input file")
}
defer imgFile.Close()
defer imgFileConfig.Close()
img, _, imgErr := image.Decode(imgFile)
config, _, confErr := image.DecodeConfig(imgFileConfig)
if imgErr != nil || confErr != nil {
log.Fatal("Error reading image file")
}
if config.Width%16 != 0 || config.Height%16 != 0 {
log.Fatal("The image width and/or height was not a multiple of 16")
}
palette := Palette{}
// If a pallete has been provided use that
if len(palettes) > 0 {
palette = palettes[0]
// Otherwise, generate one based on the image
} else {
tempPalette := Palette{}
for x := 0; x < config.Width; x++ {
for y := 0; y < config.Height; y++ {
colourString, colourRGBA := getColourStringAndRGBA(img.At(x, y))
tempPalette[colourString] = colourRGBA
}
}
if len(tempPalette) > 16 {
log.Fatal("More than 16 colours used in image palette")
}
paletteSlots := []string{"0", "1", "2", "3", "4", "5", "6", "7", "8", "9", "a", "b", "c", "d", "e", "f"}
slotCount := 0
for _, colour := range tempPalette {
palette[paletteSlots[slotCount]] = colour
slotCount++
}
}
// Get palette slot for each pixel
sprites := map[string][]string{}
for y := 0; y < config.Height; y++ {
spriteCountY := int(math.Floor(float64(y) / 16))
for x := 0; x < config.Width; x++ {
spriteCountX := int(math.Floor(float64(x) / 16))
spriteCoord := strconv.Itoa(spriteCountX) + "," + strconv.Itoa(spriteCountY)
_, colourRGBA := getColourStringAndRGBA(img.At(x, y))
for paletteSlot, paletteColour := range palette {
if paletteColour == colourRGBA {
sprites[spriteCoord] = append(sprites[spriteCoord], paletteSlot)
}
}
}
}
// Build up the output file
spriteStrings := []string{}
spriteNames := []string{}
// Palette
paletteName := "palette_" + exportedSpriteName
paletteString := "var " + paletteName + " = &engine.Palette{"
for paletteSlot, colour := range palette {
paletteString += `"` + paletteSlot + `": color.RGBA{` + strconv.Itoa(int(colour.R)) + `,` + strconv.Itoa(int(colour.G)) + `,` + strconv.Itoa(int(colour.B)) + `,` + strconv.Itoa(int(colour.A)) + `},`
}
paletteString += "}"
// Sprites
for y := 0; y < (config.Height / 16); y++ {
for x := 0; x < (config.Width / 16); x++ {
spriteName := "sprite_" + exportedSpriteName + "_" + strconv.Itoa(x) + "_" + strconv.Itoa(y)
spriteString := "var " + spriteName + ", _ = engine.CreateSprite(" + paletteName + ", []int{"
spriteNames = append(spriteNames, spriteName)
for i, paletteSlot := range sprites[strconv.Itoa(x)+","+strconv.Itoa(y)] {
if (i % 8) == 0 {
spriteString += "0x"
}
spriteString += paletteSlot
if (i % 8) == 7 {
spriteString += ","
}
}
spriteString += "}}"
spriteStrings = append(spriteStrings, spriteString)
}
}
fileContents := `package ` + packageName + `
import (
"image/color"
"github.com/tesh254/lakra/engine"
)
` + paletteString + `
` + strings.Join(spriteStrings, "\n") +`
var ` + exportedSpriteName + `, _ = engine.CreateSpriteGroup(` + strconv.Itoa(config.Width/16) + `, ` + strconv.Itoa(config.Height/16) + `, &[]*engine.Sprite{` + strings.Join(spriteNames, ",") + `}}`
// Write the output file to disk
err := ioutil.WriteFile(outputFile, []byte(fileContents), 0644)
if err != nil {
log.Fatal("Error writing to output file")
}
}
// getColourStringAndRGBA converts a color.Color object to its string and color.RGBA representations
func getColourStringAndRGBA(colour color.Color) (string, color.RGBA) {
r, g, b, a := colour.RGBA()
colourString := strconv.Itoa(int(r)) + "," + strconv.Itoa(int(g)) + "," + strconv.Itoa(int(b)) + "," + strconv.Itoa(int(a))
colourRGBA := color.RGBA{uint8(r), uint8(g), uint8(b), uint8(a)}
return colourString, colourRGBA
}