94 lines
3.0 KiB
Go
94 lines
3.0 KiB
Go
package level
|
|
|
|
import "github.com/inkyblackness/hacked/ss1/serial"
|
|
|
|
// TileMapEntry describes one tile of the map.
|
|
type TileMapEntry struct {
|
|
// Type indicates what kind of tile this is.
|
|
Type TileType
|
|
// Floor describes floor properties.
|
|
Floor FloorInfo
|
|
// Ceiling describes ceiling properties.
|
|
Ceiling CeilingInfo
|
|
// SlopeHeight indicates for non-flat tiles the height offset.
|
|
SlopeHeight TileHeightUnit
|
|
|
|
// FirstObjectIndex points into the level object cross reference table to the first object in this tile.
|
|
FirstObjectIndex int16
|
|
// TextureInfo describes tile texturing.
|
|
TextureInfo TileTextureInfo
|
|
// Flags contains arbitrary additional information.
|
|
Flags TileFlag
|
|
|
|
// SubClip is always 0xFF.
|
|
SubClip byte
|
|
_ [2]byte
|
|
// LightDelta describes the light offsets of this tile.
|
|
LightDelta LightDeltaInfo
|
|
}
|
|
|
|
// Reset puts the tile into an initial state.
|
|
func (tile *TileMapEntry) Reset() {
|
|
*tile = TileMapEntry{}
|
|
tile.SubClip = 0xFF
|
|
}
|
|
|
|
// FloorTileHeightAt returns the height of the floor (in tile unit) at the given fine position.
|
|
func (tile TileMapEntry) FloorTileHeightAt(pos FinePosition, height HeightShift) float32 {
|
|
floorHeight, _ := height.ValueFromTileHeight(tile.Floor.AbsoluteHeight())
|
|
if tile.Flags.SlopeControl() == TileSlopeControlFloorFlat {
|
|
return floorHeight
|
|
}
|
|
slopeHeight, _ := height.ValueFromTileHeight(tile.SlopeHeight)
|
|
fineHeight := slopeHeight * pos.SlopeFactorFor(tile.Type)
|
|
return floorHeight + fineHeight
|
|
}
|
|
|
|
// CeilingTileHeightAt returns the height of the ceiling (in tile unit) at the given fine position.
|
|
func (tile TileMapEntry) CeilingTileHeightAt(pos FinePosition, height HeightShift) float32 {
|
|
ceilingHeight, _ := height.ValueFromTileHeight(tile.Ceiling.AbsoluteHeight())
|
|
slopeControl := tile.Flags.SlopeControl()
|
|
if slopeControl == TileSlopeControlCeilingFlat {
|
|
return ceilingHeight
|
|
}
|
|
slopeHeight, _ := height.ValueFromTileHeight(tile.SlopeHeight)
|
|
var slopeFactor float32
|
|
if slopeControl == TileSlopeControlCeilingMirrored {
|
|
slopeFactor = pos.SlopeFactorFor(tile.Type)
|
|
} else {
|
|
slopeFactor = pos.SlopeFactorFor(tile.Type.Info().SlopeInvertedType)
|
|
}
|
|
fineHeight := slopeHeight * slopeFactor
|
|
return ceilingHeight - fineHeight
|
|
}
|
|
|
|
// TileMap is a rectangular set of tiles.
|
|
// The first index is the Y-axis, the second index the X-axis. This way the map can be serialized quicker.
|
|
type TileMap struct {
|
|
entries []TileMapEntry
|
|
}
|
|
|
|
// NewTileMap returns a new, initialized map.
|
|
func NewTileMap(width, height int) TileMap {
|
|
entries := make([]TileMapEntry, width*height)
|
|
for i := 0; i < len(entries); i++ {
|
|
entries[i].Reset()
|
|
}
|
|
return TileMap{entries: entries}
|
|
}
|
|
|
|
// Tile returns a pointer to the tile within the map for given position.
|
|
// Nil is returned for a coordinate outside the boundaries.
|
|
func (m TileMap) Tile(pos TilePosition, xShift int) *TileMapEntry {
|
|
index := int(pos.X) + (int(pos.Y) << xShift)
|
|
if (int(pos.X) >= (1 << xShift)) || (index >= len(m.entries)) {
|
|
return nil
|
|
}
|
|
return &m.entries[index]
|
|
}
|
|
|
|
// Code serializes the map.
|
|
func (m TileMap) Code(coder serial.Coder) {
|
|
coder.Code(m.entries)
|
|
}
|