Render multiple Z levels

Performance regression warning: this is now quite slow to render when showing
all 7 Z levels. Bounds clipping may be enough to get it back to acceptable
levels, or we may have to do something cleverer
This commit is contained in:
2018-03-25 12:11:48 +01:00
parent 6a90bb16cf
commit 50d316b5eb

View File

@@ -112,10 +112,10 @@ func (e *env) run() {
})
}
func (e *env) getSprite(palette []string, ref maps.ObjRef) (*conv.Sprite, *conv.Object) {
func (e *env) getSprite(palette []string, ref maps.ObjRef) *conv.Sprite {
if ref.Index() >= len(palette) {
log.Printf("Palette too small: %v requested", ref.Index())
return nil, nil
return nil
}
name := palette[ref.Index()]
@@ -123,15 +123,15 @@ func (e *env) getSprite(palette []string, ref maps.ObjRef) (*conv.Sprite, *conv.
obj := e.objects[name]
if obj == nil {
log.Printf("Failed to find surface sprite %#v -> %q", ref, name)
return nil, nil
return nil
}
if ref.Frame() >= len(obj.Sprites) {
log.Printf("Out-of-index sprite %v requested for %v", ref.Frame(), name)
return nil, obj
return nil
}
return &obj.Sprites[ref.Frame()], obj
return &obj.Sprites[ref.Frame()]
}
var (
@@ -142,8 +142,6 @@ var (
// TODO: build all the sprites in the set into a single spritesheet so we can
// use pixel.Batch
func (s *state) present(pWin *pixelgl.Window) {
gameMap := s.env.gameMap
pWin.Clear(colornames.Black)
center := pWin.Bounds().Center()
@@ -156,45 +154,56 @@ func (s *state) present(pWin *pixelgl.Window) {
s.cam = cam
pWin.SetMatrix(cam)
// TODO: bounds clipping
z := int(s.zIdx)
for y := int(gameMap.MinLength); y < int(gameMap.MaxLength); y++ {
for x := int(gameMap.MinWidth); x < int(gameMap.MaxWidth); x++ {
// TODO: we should be able to perform bounds clipping on these
minX := int(s.env.gameMap.MinWidth)
maxX := int(s.env.gameMap.MaxWidth)
minY := int(s.env.gameMap.MinLength)
maxY := int(s.env.gameMap.MaxLength)
minZ := 0
maxZ := int(s.zIdx) + 1
cell := gameMap.Cells.At(x, y, z)
surfaceSprite, _ := s.env.getSprite(s.env.set.Palette, cell.Surface)
centerSprite, _ := s.env.getSprite(s.env.set.Palette, cell.Center)
leftSprite, _ := s.env.getSprite(s.env.set.Palette, cell.Left)
rightSprite, _ := s.env.getSprite(s.env.set.Palette, cell.Right)
fX := float64(x)
fY := float64(y)
xPos := fX * cellWidth
yPos := fY * cellLength
// The rotation translates the rectangular coordinates to diamond
// ones \o/
// FIXME: these are off by a bit
orig := pixel.V(xPos, yPos)
iso := pixel.V(orig.X-orig.Y, (orig.X+orig.Y)/2.0)
if surfaceSprite != nil {
surfaceSprite.Spr.Draw(pWin, pixel.IM.Moved(iso))
for z := minZ; z < maxZ; z++ {
for y := minY; y < maxY; y++ {
for x := minX; x < maxX; x++ {
s.renderCell(x, y, z, pWin)
}
}
}
}
if centerSprite != nil {
centerSprite.Spr.Draw(pWin, pixel.IM.Moved(iso))
}
func (s *state) renderCell(x, y, z int, pWin *pixelgl.Window) {
var sprites []*conv.Sprite
if leftSprite != nil {
leftSprite.Spr.Draw(pWin, pixel.IM.Moved(iso))
}
cell := s.env.gameMap.Cells.At(x, y, z)
if rightSprite != nil {
rightSprite.Spr.Draw(pWin, pixel.IM.Moved(iso))
}
// Try optimizing zero surfaces out, they tend to be? all-transparent
if cell.Surface.Index() != 0 {
sprites = append(sprites, s.env.getSprite(s.env.set.Palette, cell.Surface))
}
sprites = append(
sprites,
s.env.getSprite(s.env.set.Palette, cell.Center),
s.env.getSprite(s.env.set.Palette, cell.Left),
s.env.getSprite(s.env.set.Palette, cell.Right),
)
// Taking the Z index away *seems* to draw the object in the correct place.
// FIXME: There are some artifacts, investigate more
fX := float64(x - z)
fY := float64(y - z)
xPos := fX * cellWidth
yPos := fY * cellLength
// The rotation translates the rectangular coordinates to diamond
// ones \o/
orig := pixel.V(xPos, yPos)
iso := pixel.V(orig.X-orig.Y, (orig.X+orig.Y)/2.0)
for _, sprite := range sprites {
if sprite != nil {
sprite.Spr.Draw(pWin, pixel.IM.Moved(iso))
}
}
}