Compare commits

...

3 Commits

Author SHA1 Message Date
132670507c Get SaW maps displaying 2020-05-31 15:01:46 +01:00
cf58be6a20 Use map rect 2020-05-31 14:58:46 +01:00
14fdab72a0 Update ebiten to v1.11.1
This seems like a significant performance boost. I get 60fps now \o/
2020-05-31 14:50:11 +01:00
6 changed files with 81 additions and 65 deletions

View File

@@ -127,13 +127,14 @@ func loadMapsFrom(part string) {
log.Printf("Maps in %s:", mapsPath) log.Printf("Maps in %s:", mapsPath)
for key, gameMap := range gameMaps { for key, gameMap := range gameMaps {
rect := gameMap.Rect()
hdr := gameMap.Header hdr := gameMap.Header
fmt.Printf( fmt.Printf(
" * `%s`: IsCampaignMap=%v W=%v:%v L=%v:%v SetName=%s\n", " * `%s`: IsCampaignMap=%v W=%v:%v L=%v:%v SetName=%s\n",
key, key,
hdr.IsCampaignMap, hdr.IsCampaignMap,
hdr.MinWidth, hdr.MaxWidth, rect.Min.X, rect.Max.X,
hdr.MinLength, hdr.MaxLength, rect.Min.Y, rect.Max.Y,
string(hdr.SetName[:]), string(hdr.SetName[:]),
) )
} }

View File

@@ -172,18 +172,15 @@ func (e *env) Update(screenX, screenY int) error {
func (e *env) Draw(screen *ebiten.Image) error { func (e *env) Draw(screen *ebiten.Image) error {
gameMap := e.gameMap gameMap := e.gameMap
imd, err := ebiten.NewImage( rect := gameMap.Rect()
int(gameMap.MaxWidth), imd, err := ebiten.NewImage(rect.Dx(), rect.Dy(), ebiten.FilterDefault)
int(gameMap.MaxLength),
ebiten.FilterDefault,
)
if err != nil { if err != nil {
return err return err
} }
for y := int(gameMap.MinLength); y < int(gameMap.MaxLength); y++ { for y := int(rect.Min.Y); y < int(rect.Max.Y); y++ {
for x := int(gameMap.MinWidth); x < int(gameMap.MaxWidth); x++ { for x := int(rect.Min.X); x < int(rect.Max.X); x++ {
cell := gameMap.Cells.At(x, y, int(e.state.zIdx)) cell := gameMap.Cells.At(x, y, int(e.state.zIdx))
imd.Set(x, y, makeColour(&cell, e.state.cellIdx)) imd.Set(x, y, makeColour(&cell, e.state.cellIdx))
} }

4
go.mod
View File

@@ -1,11 +1,11 @@
module code.ur.gs/lupine/ordoor module code.ur.gs/lupine/ordoor
go 1.12 go 1.14
require ( require (
github.com/BurntSushi/toml v0.3.1 github.com/BurntSushi/toml v0.3.1
github.com/emef/bitfield v0.0.0-20170503144143-7d3f8f823065 github.com/emef/bitfield v0.0.0-20170503144143-7d3f8f823065
github.com/hajimehoshi/ebiten v1.11.0 github.com/hajimehoshi/ebiten v1.11.1
github.com/jfreymuth/oggvorbis v1.0.1 // indirect github.com/jfreymuth/oggvorbis v1.0.1 // indirect
github.com/kr/text v0.2.0 // indirect github.com/kr/text v0.2.0 // indirect
github.com/niemeyer/pretty v0.0.0-20200227124842-a10e7caefd8e // indirect github.com/niemeyer/pretty v0.0.0-20200227124842-a10e7caefd8e // indirect

2
go.sum
View File

@@ -19,6 +19,8 @@ github.com/hajimehoshi/ebiten v1.11.0-alpha.2.0.20200101150127-38815ba801a5 h1:h
github.com/hajimehoshi/ebiten v1.11.0-alpha.2.0.20200101150127-38815ba801a5/go.mod h1:0SLvfr8iI2NxzpNB/olBM+dLN9Ur5a9szG13wOgQ0nQ= github.com/hajimehoshi/ebiten v1.11.0-alpha.2.0.20200101150127-38815ba801a5/go.mod h1:0SLvfr8iI2NxzpNB/olBM+dLN9Ur5a9szG13wOgQ0nQ=
github.com/hajimehoshi/ebiten v1.11.0 h1:+pIxfzfVgRbHGM7wBAJtgzPiWiZopA7lyIKNQqc9amk= github.com/hajimehoshi/ebiten v1.11.0 h1:+pIxfzfVgRbHGM7wBAJtgzPiWiZopA7lyIKNQqc9amk=
github.com/hajimehoshi/ebiten v1.11.0/go.mod h1:aDEhx0K9gSpXw3Cxf2hCXDxPSoF8vgjNqKxrZa/B4Dg= github.com/hajimehoshi/ebiten v1.11.0/go.mod h1:aDEhx0K9gSpXw3Cxf2hCXDxPSoF8vgjNqKxrZa/B4Dg=
github.com/hajimehoshi/ebiten v1.11.1 h1:7gy2bHBDNtfTh3GlcUAilk3lNWW9fTLaP7iZAodS9F8=
github.com/hajimehoshi/ebiten v1.11.1/go.mod h1:aDEhx0K9gSpXw3Cxf2hCXDxPSoF8vgjNqKxrZa/B4Dg=
github.com/hajimehoshi/go-mp3 v0.2.1 h1:DH4ns3cPv39n3cs8MPcAlWqPeAwLCK8iNgqvg0QBWI8= github.com/hajimehoshi/go-mp3 v0.2.1 h1:DH4ns3cPv39n3cs8MPcAlWqPeAwLCK8iNgqvg0QBWI8=
github.com/hajimehoshi/go-mp3 v0.2.1/go.mod h1:Rr+2P46iH6PwTPVgSsEwBkon0CK5DxCAeX/Rp65DCTE= github.com/hajimehoshi/go-mp3 v0.2.1/go.mod h1:Rr+2P46iH6PwTPVgSsEwBkon0CK5DxCAeX/Rp65DCTE=
github.com/hajimehoshi/oto v0.3.4/go.mod h1:PgjqsBJff0efqL2nlMJidJgVJywLn6M4y8PI4TfeWfA= github.com/hajimehoshi/oto v0.3.4/go.mod h1:PgjqsBJff0efqL2nlMJidJgVJywLn6M4y8PI4TfeWfA=

View File

@@ -15,8 +15,8 @@ import (
) )
var ( var (
expectedMagic = []byte("\x08\x00WHMAP\x00") expectedMagic = []byte("\x15\x00AMB_MAP\x00")
expectedSetNameOffset = uint32(0x34) expectedSetNameOffset = uint32(0x10)
notImplemented = fmt.Errorf("Not implemented") notImplemented = fmt.Errorf("Not implemented")
) )
@@ -25,35 +25,25 @@ const (
MaxLength = 100 // Y coordinate MaxLength = 100 // Y coordinate
MaxWidth = 130 // X coordinate MaxWidth = 130 // X coordinate
CellSize = 16 // seems to be CellSize = 13 // seems to be
cellDataOffset = 0x110 // definitely cellDataOffset = 0xc0
cellCount = MaxHeight * MaxLength * MaxWidth cellCount = MaxHeight * MaxLength * MaxWidth
) )
type Header struct { type Header struct {
IsCampaignMap uint32 // Tentatively: 0 = no, 1 = yes Magic [10]byte // "\x15\x00AMB_MAP\x00"
MinWidth uint32 SetName [8]byte // Links to a filename in `/Sets/*.set`
MinLength uint32
MaxWidth uint32
MaxLength uint32
Unknown1 uint32
Unknown2 uint32
Unknown3 uint32
Unknown4 uint32
Magic [8]byte // "\x08\x00WHMAP\x00"
Unknown5 uint32
Unknown6 uint32
SetName [8]byte // Links to a filename in `/Sets/*.set`
// Need to investigate the rest of the header too // Need to investigate the rest of the header too
IsCampaignMap byte
} }
func (h Header) Width() int { func (h Header) Width() int {
return int(h.MaxWidth - h.MinWidth) return MaxWidth
} }
func (h Header) Length() int { func (h Header) Length() int {
return int(h.MaxLength - h.MinLength) return MaxLength
} }
func (h Header) Height() int { func (h Header) Height() int {
@@ -80,7 +70,7 @@ type ObjRef struct {
// The index into a set palette to retrieve the object // The index into a set palette to retrieve the object
func (o ObjRef) Index() int { func (o ObjRef) Index() int {
return int(o.AreaByte) return int(o.AreaByte & 0x7f)
} }
func (o ObjRef) Sprite() int { func (o ObjRef) Sprite() int {
@@ -91,12 +81,13 @@ func (o ObjRef) Sprite() int {
// The top bit seems to say whether we should draw or not. // The top bit seems to say whether we should draw or not.
func (o ObjRef) IsActive() bool { func (o ObjRef) IsActive() bool {
return (o.SpriteAndFlagByte & 0x80) == 0x80 return (o.SpriteAndFlagByte & 0x80) == 0x80
} } // PARIS is 78 x 60 x 7
// 4E 3C 7
/*
type Cell struct { type Cell struct {
DoorAndCanisterRelated byte DoorAndCanisterRelated byte
DoorLockAndReactorRelated byte // DoorLockAndReactorRelated byte
Unknown2 byte // Unknown2 byte
Surface ObjRef Surface ObjRef
Left ObjRef Left ObjRef
Right ObjRef Right ObjRef
@@ -105,43 +96,60 @@ type Cell struct {
Unknown12 byte Unknown12 byte
Unknown13 byte Unknown13 byte
Unknown14 byte Unknown14 byte
SquadRelated byte // SquadRelated byte
}*/
type Cell struct {
Unknown1 byte
Surface ObjRef
Left ObjRef
Right ObjRef
Center ObjRef
Unknown2 [4]byte
/*
DoorAndCanisterRelated byte
// DoorLockAndReactorRelated byte
// Unknown2 byte
Surface ObjRef
Left ObjRef
Right ObjRef
Center ObjRef
Unknown11 byte
Unknown12 byte
Unknown13 byte
Unknown14 byte
SquadRelated byte*/
} }
func (c *Cell) At(n int) byte { func (c *Cell) At(n int) byte {
switch n { switch n {
case 0: case 0:
return c.DoorAndCanisterRelated return c.Unknown1
case 1: case 1:
return c.DoorLockAndReactorRelated
case 2:
return c.Unknown2
case 3:
return c.Surface.AreaByte return c.Surface.AreaByte
case 4: case 2:
return c.Surface.SpriteAndFlagByte return c.Surface.SpriteAndFlagByte
case 5: case 3:
return c.Left.AreaByte return c.Left.AreaByte
case 6: case 4:
return c.Left.SpriteAndFlagByte return c.Left.SpriteAndFlagByte
case 7: case 5:
return c.Right.AreaByte return c.Right.AreaByte
case 8: case 6:
return c.Right.SpriteAndFlagByte return c.Right.SpriteAndFlagByte
case 9: case 7:
return c.Center.AreaByte return c.Center.AreaByte
case 10: case 8:
return c.Center.SpriteAndFlagByte return c.Center.SpriteAndFlagByte
case 9:
return c.Unknown2[0]
case 10:
return c.Unknown2[1]
case 11: case 11:
return c.Unknown11 return c.Unknown2[2]
case 12: case 12:
return c.Unknown12 return c.Unknown2[3]
case 13:
return c.Unknown13
case 14:
return c.Unknown14
case 15:
return c.SquadRelated
} }
return 0 return 0
@@ -150,15 +158,23 @@ func (c *Cell) At(n int) byte {
// Cells is always a fixed size; use At to get a cell according to x,y,z // Cells is always a fixed size; use At to get a cell according to x,y,z
type Cells []Cell type Cells []Cell
// 6 Possibilities for being laid out in memory. Most likely:
// XXYYZZ
// OR
// XYZXYZ
func (c Cells) At(x, y, z int) Cell { func (c Cells) At(x, y, z int) Cell {
return c[(z*MaxLength*MaxWidth)+(y*MaxWidth)+x] // log.Printf("At (%v,%v,%v)=%v", x, y, z, x*y*z)
return c[(z*MaxLength*MaxWidth)+
(y*MaxWidth)+
x]
} }
func (h Header) Check() []error { func (h Header) Check() []error {
var out []error var out []error
if h.IsCampaignMap > 1 { // if h.IsCampaignMap > 1 {
out = append(out, fmt.Errorf("Expected 0 or 1 for IsCampaignMap, got %v", h.IsCampaignMap)) // out = append(out, fmt.Errorf("Expected 0 or 1 for IsCampaignMap, got %v", h.IsCampaignMap))
} // }
if bytes.Compare(expectedMagic, h.Magic[:]) != 0 { if bytes.Compare(expectedMagic, h.Magic[:]) != 0 {
out = append(out, fmt.Errorf("Unexpected magic value: %v", h.Magic)) out = append(out, fmt.Errorf("Unexpected magic value: %v", h.Magic))
@@ -176,10 +192,10 @@ type GameMap struct {
func (m *GameMap) Rect() image.Rectangle { func (m *GameMap) Rect() image.Rectangle {
return image.Rect( return image.Rect(
int(m.Header.MinWidth), int(0),
int(m.Header.MinLength), int(0),
int(m.Header.MaxWidth), int(m.Width()-1),
int(m.Header.MaxLength), int(m.Length()-1),
) )
} }

View File

@@ -6,7 +6,7 @@ import (
) )
// Override this to change the palette globally // Override this to change the palette globally
const DefaultPaletteName = "ChaosGate" const DefaultPaletteName = "SoldiersAtWar"
var ( var (
Transparent = color.RGBA{R: 0, G: 0, B: 0, A: 0} Transparent = color.RGBA{R: 0, G: 0, B: 0, A: 0}