1
1
mirror of https://github.com/OpenDiablo2/OpenDiablo2 synced 2025-02-04 23:56:40 -05:00

More map rendering updates.

This commit is contained in:
Tim Sarbin 2019-11-01 16:51:50 -04:00
parent 7d228d116e
commit 07709e2ddf
5 changed files with 178 additions and 93 deletions

View File

@ -26,15 +26,17 @@ type LevelPresetRecord struct {
Dt1Mask uint32
}
var LevelPresets []LevelPresetRecord
var LevelPresets map[int]*LevelPresetRecord
func LoadLevelPresets(fileProvider FileProvider) {
levelTypesData := fileProvider.LoadFile(ResourcePaths.LevelPreset)
sr := CreateStreamReader(levelTypesData)
numRecords := sr.GetInt32()
LevelPresets = make([]LevelPresetRecord, numRecords)
for i := range LevelPresets {
LevelPresets[i].DefinitionId = sr.GetInt32()
sr.SkipBytes(4) // Count
LevelPresets = make(map[int]*LevelPresetRecord)
for !sr.Eof() {
i := int(sr.GetInt32())
LevelPresets[i] = &LevelPresetRecord{}
LevelPresets[i].DefinitionId = int32(i)
LevelPresets[i].LevelId = sr.GetInt32()
LevelPresets[i].Populate = sr.GetInt32() != 0
LevelPresets[i].Logicals = sr.GetInt32() != 0

View File

@ -33,7 +33,7 @@ type FloorShadowRecord struct {
Unknown1 byte
MainIndex byte
Unknown2 byte
Hidden byte
Hidden bool
}
type WallRecord struct {
@ -44,7 +44,7 @@ type WallRecord struct {
Unknown1 byte
MainIndex byte
Unknown2 byte
Hidden byte
Hidden bool
}
type SubstitutionRecord struct {
@ -199,7 +199,7 @@ func LoadDS1(path string, fileProvider Common.FileProvider) *DS1 {
ds1.Tiles[y][x].Walls[wallIndex].Unknown1 = byte((dw & 0x000FC000) >> 14)
ds1.Tiles[y][x].Walls[wallIndex].MainIndex = byte((dw & 0x03F00000) >> 20)
ds1.Tiles[y][x].Walls[wallIndex].Unknown2 = byte((dw & 0x7C000000) >> 26)
ds1.Tiles[y][x].Walls[wallIndex].Hidden = byte((dw & 0x80000000) >> 31)
ds1.Tiles[y][x].Walls[wallIndex].Hidden = byte((dw&0x80000000)>>31) > 0
case LayerStreamOrientation1:
fallthrough
case LayerStreamOrientation2:
@ -225,14 +225,14 @@ func LoadDS1(path string, fileProvider Common.FileProvider) *DS1 {
ds1.Tiles[y][x].Floors[floorIndex].Unknown1 = byte((dw & 0x000FC000) >> 14)
ds1.Tiles[y][x].Floors[floorIndex].MainIndex = byte((dw & 0x03F00000) >> 20)
ds1.Tiles[y][x].Floors[floorIndex].Unknown2 = byte((dw & 0x7C000000) >> 26)
ds1.Tiles[y][x].Floors[floorIndex].Hidden = byte((dw & 0x80000000) >> 31)
ds1.Tiles[y][x].Floors[floorIndex].Hidden = byte((dw&0x80000000)>>31) > 0
case LayerStreamShadow:
ds1.Tiles[y][x].Shadows[0].Prop1 = byte(dw & 0x000000FF)
ds1.Tiles[y][x].Shadows[0].SubIndex = byte((dw & 0x00003F00) >> 8)
ds1.Tiles[y][x].Shadows[0].Unknown1 = byte((dw & 0x000FC000) >> 14)
ds1.Tiles[y][x].Shadows[0].MainIndex = byte((dw & 0x03F00000) >> 20)
ds1.Tiles[y][x].Shadows[0].Unknown2 = byte((dw & 0x7C000000) >> 26)
ds1.Tiles[y][x].Shadows[0].Hidden = byte((dw & 0x80000000) >> 31)
ds1.Tiles[y][x].Shadows[0].Hidden = byte((dw&0x80000000)>>31) > 0
case LayerStreamSubstitute:
ds1.Tiles[y][x].Substitutions[0].Unknown = dw
}

View File

@ -49,7 +49,24 @@ func (v *Engine) Render(target *ebiten.Image) {
offX := -(y * 80)
offY := y * 40
for x := 0; x < int(v.regions[0].Region.TileWidth); x++ {
v.regions[0].Region.RenderTile(400+offX+int(v.OffsetX), offY+int(v.OffsetY), x, y, RegionLayerTypeFloors, 0, target)
tile := v.regions[0].Region.DS1.Tiles[y][x]
for i := range tile.Floors {
v.regions[0].Region.RenderTile(400+offX+int(v.OffsetX), offY+int(v.OffsetY), x, y, RegionLayerTypeFloors, i, target)
}
offX += 80
offY += 40
}
}
for y := 0; y < int(v.regions[0].Region.TileHeight); y++ {
offX := -(y * 80)
offY := y * 40
for x := 0; x < int(v.regions[0].Region.TileWidth); x++ {
tile := v.regions[0].Region.DS1.Tiles[y][x]
for i := range tile.Walls {
// TODO: render back walls, then character, then fore walls
v.regions[0].Region.RenderTile(400+offX+int(v.OffsetX), offY+int(v.OffsetY), x, y, RegionLayerTypeWalls, i, target)
}
offX += 80
offY += 40
}

View File

@ -1,7 +1,6 @@
package Map
import (
"log"
"math"
"math/rand"
"strconv"
@ -21,7 +20,7 @@ type TileCacheRecord struct {
type Region struct {
levelType Common.LevelTypeRecord
levelPreset Common.LevelPresetRecord
levelPreset *Common.LevelPresetRecord
TileWidth int32
TileHeight int32
Tiles []Tile
@ -40,41 +39,41 @@ const (
type RegionIdType int
const (
RegionNoneRegionAct1Town = 1
RegionAct1Wilderness RegionIdType = 2
RegionAct1Cave RegionIdType = 3
RegionAct1Crypt RegionIdType = 4
RegionAct1Monestary RegionIdType = 5
RegionAct1Courtyard RegionIdType = 6
RegionAct1Barracks RegionIdType = 7
RegionAct1Jail RegionIdType = 8
RegionAct1Cathedral RegionIdType = 9
RegionAct1Catacombs RegionIdType = 10
RegionAct1Tristram RegionIdType = 11
RegionAct2Town RegionIdType = 12
RegionAct2Sewer RegionIdType = 13
RegionAct2Harem RegionIdType = 14
RegionAct2Basement RegionIdType = 15
RegionAct2Desert RegionIdType = 16
RegionAct2Tomb RegionIdType = 17
RegionAct2Lair RegionIdType = 18
RegionAct2Arcane RegionIdType = 19
RegionAct3Town RegionIdType = 20
RegionAct3Jungle RegionIdType = 21
RegionAct3Kurast RegionIdType = 22
RegionAct3Spider RegionIdType = 23
RegionAct3Dungeon RegionIdType = 24
RegionAct3Sewer RegionIdType = 25
RegionAct4Town RegionIdType = 26
RegionAct4Mesa RegionIdType = 27
RegionAct4Lava RegionIdType = 28
RegonAct5Town RegionIdType = 29
RegionAct5Siege RegionIdType = 30
RegionAct5Barricade RegionIdType = 31
RegionAct5Temple RegionIdType = 32
RegionAct5IceCaves RegionIdType = 33
RegionAct5Baal RegionIdType = 34
RegionAct5Lava RegionIdType = 35
RegionAct1Town RegionIdType = 1
RegionAct1Wilderness RegionIdType = 2
RegionAct1Cave RegionIdType = 3
RegionAct1Crypt RegionIdType = 4
RegionAct1Monestary RegionIdType = 5
RegionAct1Courtyard RegionIdType = 6
RegionAct1Barracks RegionIdType = 7
RegionAct1Jail RegionIdType = 8
RegionAct1Cathedral RegionIdType = 9
RegionAct1Catacombs RegionIdType = 10
RegionAct1Tristram RegionIdType = 11
RegionAct2Town RegionIdType = 12
RegionAct2Sewer RegionIdType = 13
RegionAct2Harem RegionIdType = 14
RegionAct2Basement RegionIdType = 15
RegionAct2Desert RegionIdType = 16
RegionAct2Tomb RegionIdType = 17
RegionAct2Lair RegionIdType = 18
RegionAct2Arcane RegionIdType = 19
RegionAct3Town RegionIdType = 20
RegionAct3Jungle RegionIdType = 21
RegionAct3Kurast RegionIdType = 22
RegionAct3Spider RegionIdType = 23
RegionAct3Dungeon RegionIdType = 24
RegionAct3Sewer RegionIdType = 25
RegionAct4Town RegionIdType = 26
RegionAct4Mesa RegionIdType = 27
RegionAct4Lava RegionIdType = 28
RegonAct5Town RegionIdType = 29
RegionAct5Siege RegionIdType = 30
RegionAct5Barricade RegionIdType = 31
RegionAct5Temple RegionIdType = 32
RegionAct5IceCaves RegionIdType = 33
RegionAct5Baal RegionIdType = 34
RegionAct5Lava RegionIdType = 35
)
func LoadRegion(seed rand.Source, levelType RegionIdType, levelPreset int, fileProvider Common.FileProvider) *Region {
@ -85,13 +84,15 @@ func LoadRegion(seed rand.Source, levelType RegionIdType, levelPreset int, fileP
TileCache: make(map[uint32]*TileCacheRecord),
}
result.Palette = Common.Palettes[PaletteDefs.PaletteType("act"+strconv.Itoa(int(result.levelType.Act)))]
bm := result.levelPreset.Dt1Mask
//\bm := result.levelPreset.Dt1Mask
for _, levelTypeDt1 := range result.levelType.Files {
if bm&1 == 0 {
/*
if bm&1 == 0 {
bm >>= 1
continue
}
bm >>= 1
continue
}
bm >>= 1
*/
if len(levelTypeDt1) == 0 || levelTypeDt1 == "" || levelTypeDt1 == "0" {
continue
}
@ -124,45 +125,60 @@ func (v *Region) RenderTile(offsetX, offsetY, tileX, tileY int, layerType Region
}
}
func (v *Region) getTile(mainIndex, subIndex, orientation int32) Tile {
func (v *Region) getTile(mainIndex, subIndex, orientation int32) *Tile {
// TODO: Need to support randomly grabbing tile based on x/y as there can be multiple matches for same main/sub index
for _, tile := range v.Tiles {
if tile.MainIndex != mainIndex || tile.SubIndex != subIndex || tile.Orientation != orientation {
continue
}
return tile
return &tile
}
log.Fatalf("Unknown tile ID [%d %d %d]", mainIndex, subIndex, orientation)
return Tile{}
//log.Fatalf("Unknown tile ID [%d %d %d]", mainIndex, subIndex, orientation)
return nil
}
func (v *Region) renderFloor(tile FloorShadowRecord, offsetX, offsetY int, target *ebiten.Image) {
if tile.Hidden {
return
}
tileCacheIndex := (uint32(tile.MainIndex) << 16) + (uint32(tile.SubIndex) << 8)
tileCache := v.TileCache[tileCacheIndex]
if tileCache == nil {
v.TileCache[tileCacheIndex] = v.generateFloorCache(tile)
tileCache = v.TileCache[tileCacheIndex]
}
if tileCache == nil {
return
}
opts := &ebiten.DrawImageOptions{}
opts.GeoM.Translate(float64(offsetX+tileCache.XOffset), float64(offsetY+tileCache.YOffset))
target.DrawImage(tileCache.Image, opts)
}
func (v *Region) renderWall(tile WallRecord, offsetX, offsetY int, target *ebiten.Image) {
if tile.Hidden {
return
}
if tile.Prop1 == 0 {
return
}
tileCacheIndex := (uint32(tile.MainIndex) << 16) + (uint32(tile.SubIndex) << 8) + (uint32(tile.Orientation))
tileCache := v.TileCache[tileCacheIndex]
if tileCache == nil {
v.TileCache[tileCacheIndex] = v.generateWallCache(tile)
// TODO: Temporary hack
if v.TileCache[tileCacheIndex] == nil {
return
}
tileCache = v.TileCache[tileCacheIndex]
}
opts := &ebiten.DrawImageOptions{}
opts.GeoM.Translate(float64(offsetX+tileCache.XOffset), float64(offsetY+tileCache.YOffset))
target.DrawImage(tileCache.Image, opts)
}
func (v *Region) generateFloorCache(tile FloorShadowRecord) *TileCacheRecord {
var pixels []byte
tileData := v.getTile(int32(tile.MainIndex), int32(tile.SubIndex), 0)
tileYMinimum := int32(0)
for _, block := range tileData.Blocks {
tileYMinimum = Common.MinInt32(tileYMinimum, int32(block.Y))
}
tileYOffset := Common.AbsInt32(tileYMinimum)
tileHeight := Common.AbsInt32(tileData.Height)
image, _ := ebiten.NewImage(int(tileData.Width), int(tileHeight), ebiten.FilterNearest)
special := false
pixels = make([]byte, 4*tileData.Width*tileHeight)
for _, block := range tileData.Blocks {
func (v *Region) decodeFloorData(blocks []Block, pixels []byte, tileYOffset int32, tileWidth int32) {
for _, block := range blocks {
// TODO: Move this to a less stupid place
if block.Format == BlockFormatIsometric {
// 3D isometric decoding
@ -182,12 +198,12 @@ func (v *Region) generateFloorCache(tile FloorShadowRecord) *TileCacheRecord {
colorIndex := block.EncodedData[idx]
if colorIndex != 0 {
pixelColor := v.Palette.Colors[colorIndex]
pixels[(4 * (((blockY + y) * tileData.Width) + (blockX + x)))] = pixelColor.R
pixels[(4*(((blockY+y)*tileData.Width)+(blockX+x)))+1] = pixelColor.G
pixels[(4*(((blockY+y)*tileData.Width)+(blockX+x)))+2] = pixelColor.B
pixels[(4*(((blockY+y)*tileData.Width)+(blockX+x)))+3] = 255
pixels[(4 * (((blockY + y) * tileWidth) + (blockX + x)))] = pixelColor.R
pixels[(4*(((blockY+y)*tileWidth)+(blockX+x)))+1] = pixelColor.G
pixels[(4*(((blockY+y)*tileWidth)+(blockX+x)))+2] = pixelColor.B
pixels[(4*(((blockY+y)*tileWidth)+(blockX+x)))+3] = 255
} else {
pixels[(4*(((blockY+y)*tileData.Width)+(blockX+x)))+3] = 0
pixels[(4*(((blockY+y)*tileWidth)+(blockX+x)))+3] = 0
}
x++
n--
@ -197,7 +213,6 @@ func (v *Region) generateFloorCache(tile FloorShadowRecord) *TileCacheRecord {
}
} else {
// RLE Encoding
special = true
blockX := int32(block.X)
blockY := int32(block.Y)
x := int32(0)
@ -220,12 +235,12 @@ func (v *Region) generateFloorCache(tile FloorShadowRecord) *TileCacheRecord {
colorIndex := block.EncodedData[idx]
if colorIndex != 0 {
pixelColor := v.Palette.Colors[colorIndex]
pixels[(4 * (((blockY + y + tileYOffset) * tileData.Width) + (blockX + x)))] = pixelColor.R
pixels[(4*(((blockY+y+tileYOffset)*tileData.Width)+(blockX+x)))+1] = pixelColor.G
pixels[(4*(((blockY+y+tileYOffset)*tileData.Width)+(blockX+x)))+2] = pixelColor.B
pixels[(4*(((blockY+y+tileYOffset)*tileData.Width)+(blockX+x)))+3] = 255
pixels[(4 * (((blockY + y + tileYOffset) * tileWidth) + (blockX + x)))] = pixelColor.R
pixels[(4*(((blockY+y+tileYOffset)*tileWidth)+(blockX+x)))+1] = pixelColor.G
pixels[(4*(((blockY+y+tileYOffset)*tileWidth)+(blockX+x)))+2] = pixelColor.B
pixels[(4*(((blockY+y+tileYOffset)*tileWidth)+(blockX+x)))+3] = 255
} else {
pixels[(4*(((blockY+y+tileYOffset)*tileData.Width)+(blockX+x)))+3] = 0
pixels[(4*(((blockY+y+tileYOffset)*tileWidth)+(blockX+x)))+3] = 0
}
idx++
x++
@ -234,18 +249,55 @@ func (v *Region) generateFloorCache(tile FloorShadowRecord) *TileCacheRecord {
}
}
}
}
func (v *Region) generateFloorCache(tile FloorShadowRecord) *TileCacheRecord {
tileData := v.getTile(int32(tile.MainIndex), int32(tile.SubIndex), 0)
if tileData == nil {
return nil
}
tileYMinimum := int32(0)
for _, block := range tileData.Blocks {
tileYMinimum = Common.MinInt32(tileYMinimum, int32(block.Y))
}
tileYOffset := Common.AbsInt32(tileYMinimum)
tileHeight := Common.AbsInt32(tileData.Height)
image, _ := ebiten.NewImage(int(tileData.Width), int(tileHeight), ebiten.FilterNearest)
pixels := make([]byte, 4*tileData.Width*tileHeight)
v.decodeFloorData(tileData.Blocks, pixels, tileYOffset, tileData.Width)
image.ReplacePixels(pixels)
yOffset := 0
if special {
yOffset = int(128 + tileData.Height)
return &TileCacheRecord{image, 0, 0}
}
func (v *Region) generateWallCache(tile WallRecord) *TileCacheRecord {
tileData := v.getTile(int32(tile.MainIndex), int32(tile.SubIndex), int32(tile.Orientation))
if tileData == nil {
return nil
}
tileYMinimum := int32(0)
for _, block := range tileData.Blocks {
tileYMinimum = Common.MinInt32(tileYMinimum, int32(block.Y))
}
tileYOffset := -tileYMinimum
tileHeight := Common.AbsInt32(tileData.Height)
image, _ := ebiten.NewImage(int(tileData.Width), int(tileHeight), ebiten.FilterNearest)
pixels := make([]byte, 4*tileData.Width*tileHeight)
v.decodeFloorData(tileData.Blocks, pixels, tileYOffset, tileData.Width)
image.ReplacePixels(pixels)
yAdjust := 0
if tile.Orientation == 15 {
// Roof
yAdjust = -int(tileData.RoofHeight)
} else if tile.Orientation > 15 {
// Lower walls
yAdjust = int(tileYMinimum) + 80
} else {
// Upper Walls
yAdjust = int(tileYMinimum) + 80
}
return &TileCacheRecord{
image,
int(tileData.Width),
yOffset,
0,
yAdjust,
}
}
func (v *Region) renderWall(tile WallRecord, offsetX, offsetY int, target *ebiten.Image) {
}

View File

@ -40,7 +40,21 @@ func (v *MapEngineTest) Load() []func() {
return []func(){
func() {
v.mapEngine = Map.CreateMapEngine(v.gameState, v.soundManager, v.fileProvider)
v.mapEngine.GenerateMap(Map.RegionAct1Tristram, 300)
//v.mapEngine.GenerateMap(Map.RegionAct2Harem, 353)
v.mapEngine.GenerateMap(Map.RegionAct1Town, 1)
//v.mapEngine.GenerateMap(Map.RegionAct1Tristram, 300)
//v.mapEngine.GenerateMap(Map.RegionAct3Town, 529)
//v.mapEngine.GenerateMap(Map.RegionAct1Cathedral, 257)
//v.mapEngine.GenerateMap(Map.RegionAct5IceCaves, 1038)
//v.mapEngine.GenerateMap(Map.RegionAct3Jungle, 574)
// Completely broken ----------------------------------------------
//v.mapEngine.GenerateMap(Map.RegonAct5Town, 863) // CRASHES
// v.mapEngine.GenerateMap(Map.RegionAct5Siege, 879) // CRASHES
//v.mapEngine.GenerateMap(Map.RegionAct5Lava, 1057) // PALETTE ISSUE
// v.mapEngine.GenerateMap(Map.RegionAct2Town, 301) // Really broken rendering
},
}
}