Sander Schobers
b85ac17d8a
Moveds fonts to separate directory & added corresponding license texts. Moved console & fps to separte gut (game utility) package. Added console (view only).
127 lines
2.7 KiB
Go
127 lines
2.7 KiB
Go
package main
|
|
|
|
import (
|
|
"errors"
|
|
"io"
|
|
"strconv"
|
|
"strings"
|
|
|
|
"opslag.de/schobers/geom"
|
|
)
|
|
|
|
type sprite struct {
|
|
texture string
|
|
parts []spritePart
|
|
}
|
|
|
|
type spritePart struct {
|
|
name string
|
|
sub geom.Rectangle
|
|
anchor geom.Point
|
|
}
|
|
|
|
func loadSpriteAsset(r io.Reader) (sprite, error) {
|
|
var l sprite
|
|
ctx := spriteContext{&l, nil}
|
|
err := parseLines(r, ctx.parse)
|
|
if err != nil {
|
|
return sprite{}, err
|
|
}
|
|
return l, nil
|
|
}
|
|
|
|
type spriteContext struct {
|
|
sprite *sprite
|
|
part *spritePart
|
|
}
|
|
|
|
func (c *spriteContext) parse(p *lineParser) parseLineFn {
|
|
if p.skipSpaceEOF() {
|
|
return nil
|
|
}
|
|
line := p.peek()
|
|
switch {
|
|
case strings.HasPrefix(line, "sprite:"):
|
|
p.next()
|
|
return c.parseContent
|
|
default:
|
|
return nil
|
|
}
|
|
}
|
|
|
|
func (c *spriteContext) parseContent(p *lineParser) parseLineFn {
|
|
const partTag = "part:"
|
|
const textureTag = "texture:"
|
|
const spriteEndTag = ":sprite"
|
|
if p.skipSpaceEOF() {
|
|
return p.emitErr(errUnexpectedEnd)
|
|
}
|
|
line := p.peek()
|
|
switch {
|
|
case strings.HasPrefix(line, textureTag):
|
|
c.sprite.texture = strings.TrimSpace(line[len(textureTag):])
|
|
p.next()
|
|
return c.parseContent
|
|
case line == partTag:
|
|
p.next()
|
|
c.part = &spritePart{}
|
|
return c.parsePart
|
|
case line == spriteEndTag:
|
|
return nil
|
|
}
|
|
return p.emitErr(errors.New("unexpected content of sprite"))
|
|
}
|
|
|
|
func (c *spriteContext) parsePart(p *lineParser) parseLineFn {
|
|
mustAtois := func(s ...string) []int {
|
|
res := make([]int, len(s))
|
|
var err error
|
|
for i, s := range s {
|
|
res[i], err = strconv.Atoi(s)
|
|
if err != nil {
|
|
panic("string does not represent an integer")
|
|
}
|
|
}
|
|
return res
|
|
}
|
|
mustCoords := func(s string) []int {
|
|
coords := strings.Split(strings.TrimSpace(s), ",")
|
|
return mustAtois(coords...)
|
|
}
|
|
const nameTag = "name:"
|
|
const subTextureTag = "sub_texture:"
|
|
const anchorTag = "anchor:"
|
|
const partEndTag = ":part"
|
|
if p.skipSpaceEOF() {
|
|
return p.emitErr(errUnexpectedEnd)
|
|
}
|
|
line := p.peek()
|
|
switch {
|
|
case strings.HasPrefix(line, nameTag):
|
|
c.part.name = strings.TrimSpace(line[len(nameTag):])
|
|
p.next()
|
|
return c.parsePart
|
|
case strings.HasPrefix(line, subTextureTag):
|
|
var coords = mustCoords(line[len(subTextureTag):])
|
|
if len(coords) != 4 {
|
|
panic("expected four coordinates (min x, min y, size x, size y)")
|
|
}
|
|
c.part.sub = geom.Rect(coords[0], coords[1], coords[0]+coords[2], coords[1]+coords[3])
|
|
p.next()
|
|
return c.parsePart
|
|
case strings.HasPrefix(line, anchorTag):
|
|
var coords = mustCoords(line[len(anchorTag):])
|
|
if len(coords) != 2 {
|
|
panic("expected two coordinates (min x, min y)")
|
|
}
|
|
c.part.anchor = geom.Pt(coords[0], coords[1])
|
|
p.next()
|
|
return c.parsePart
|
|
case line == partEndTag:
|
|
c.sprite.parts = append(c.sprite.parts, *c.part)
|
|
p.next()
|
|
return c.parseContent
|
|
}
|
|
return p.emitErr(errors.New("unexpected content of part"))
|
|
}
|