mirror of
https://github.com/OpenDiablo2/OpenDiablo2
synced 2024-11-17 18:06:03 -05:00
Lots of map rendering changes.
This commit is contained in:
parent
07709e2ddf
commit
b05e887d8a
@ -24,6 +24,14 @@ func MaxInt32(a, b int32) int32 {
|
||||
return b
|
||||
}
|
||||
|
||||
func NextPow2(x int32) int32 {
|
||||
result := int32(1)
|
||||
for result < x {
|
||||
result *= 2
|
||||
}
|
||||
return result
|
||||
}
|
||||
|
||||
func AbsInt32(a int32) int32 {
|
||||
if a < 0 {
|
||||
return -a
|
||||
|
@ -51,25 +51,57 @@ func (v *Engine) Render(target *ebiten.Image) {
|
||||
for x := 0; x < int(v.regions[0].Region.TileWidth); x++ {
|
||||
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)
|
||||
if !tile.Floors[i].Hidden && tile.Floors[i].Prop1 != 0 {
|
||||
v.regions[0].Region.RenderTile(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.Shadows {
|
||||
if tile.Shadows[i].Hidden || tile.Shadows[i].Prop1 == 0 {
|
||||
continue
|
||||
}
|
||||
v.regions[0].Region.RenderTile(offX+int(v.OffsetX), offY+int(v.OffsetY), x, y, RegionLayerTypeShadows, 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)
|
||||
if tile.Walls[i].Hidden || tile.Walls[i].Orientation == 15 || tile.Walls[i].Orientation == 10 || tile.Walls[i].Orientation == 11 || tile.Walls[i].Orientation == 0 {
|
||||
continue
|
||||
}
|
||||
v.regions[0].Region.RenderTile(offX+int(v.OffsetX), offY+int(v.OffsetY), x, y, RegionLayerTypeWalls, 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 {
|
||||
if tile.Walls[i].Hidden || tile.Walls[i].Orientation != 15 {
|
||||
continue
|
||||
}
|
||||
v.regions[0].Region.RenderTile(offX+int(v.OffsetX), offY+int(v.OffsetY), x, y, RegionLayerTypeWalls, i, target)
|
||||
}
|
||||
offX += 80
|
||||
offY += 40
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
|
187
Map/Region.go
187
Map/Region.go
@ -1,6 +1,8 @@
|
||||
package Map
|
||||
|
||||
import (
|
||||
"image/color"
|
||||
"log"
|
||||
"math"
|
||||
"math/rand"
|
||||
"strconv"
|
||||
@ -26,14 +28,17 @@ type Region struct {
|
||||
Tiles []Tile
|
||||
DS1 *DS1
|
||||
Palette Common.PaletteRec
|
||||
TileCache map[uint32]*TileCacheRecord
|
||||
FloorCache map[uint32]*TileCacheRecord
|
||||
ShadowCache map[uint32]*TileCacheRecord
|
||||
WallCache map[uint32]*TileCacheRecord
|
||||
}
|
||||
|
||||
type RegionLayerType int
|
||||
|
||||
const (
|
||||
RegionLayerTypeFloors RegionLayerType = 0
|
||||
RegionLayerTypeWalls RegionLayerType = 1
|
||||
RegionLayerTypeFloors RegionLayerType = 0
|
||||
RegionLayerTypeWalls RegionLayerType = 1
|
||||
RegionLayerTypeShadows RegionLayerType = 2
|
||||
)
|
||||
|
||||
type RegionIdType int
|
||||
@ -81,7 +86,9 @@ func LoadRegion(seed rand.Source, levelType RegionIdType, levelPreset int, fileP
|
||||
levelType: Common.LevelTypes[levelType],
|
||||
levelPreset: Common.LevelPresets[levelPreset],
|
||||
Tiles: make([]Tile, 0),
|
||||
TileCache: make(map[uint32]*TileCacheRecord),
|
||||
FloorCache: make(map[uint32]*TileCacheRecord),
|
||||
ShadowCache: make(map[uint32]*TileCacheRecord),
|
||||
WallCache: make(map[uint32]*TileCacheRecord),
|
||||
}
|
||||
result.Palette = Common.Palettes[PaletteDefs.PaletteType("act"+strconv.Itoa(int(result.levelType.Act)))]
|
||||
//\bm := result.levelPreset.Dt1Mask
|
||||
@ -122,6 +129,8 @@ func (v *Region) RenderTile(offsetX, offsetY, tileX, tileY int, layerType Region
|
||||
v.renderFloor(v.DS1.Tiles[tileY][tileX].Floors[layerIndex], offsetX, offsetY, target)
|
||||
case RegionLayerTypeWalls:
|
||||
v.renderWall(v.DS1.Tiles[tileY][tileX].Walls[layerIndex], offsetX, offsetY, target)
|
||||
case RegionLayerTypeShadows:
|
||||
v.renderShadow(v.DS1.Tiles[tileY][tileX].Shadows[layerIndex], offsetX, offsetY, target)
|
||||
}
|
||||
}
|
||||
|
||||
@ -138,17 +147,14 @@ func (v *Region) getTile(mainIndex, subIndex, orientation int32) *Tile {
|
||||
}
|
||||
|
||||
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
|
||||
tileCacheIndex := (uint32(tile.MainIndex) << 16) | (uint32(tile.SubIndex) << 8)
|
||||
tileCache, exists := v.FloorCache[tileCacheIndex]
|
||||
if !exists {
|
||||
v.FloorCache[tileCacheIndex] = v.generateFloorCache(tile)
|
||||
tileCache = v.FloorCache[tileCacheIndex]
|
||||
if tileCache == nil {
|
||||
log.Fatal("Could not load floor tile")
|
||||
}
|
||||
}
|
||||
opts := &ebiten.DrawImageOptions{}
|
||||
opts.GeoM.Translate(float64(offsetX+tileCache.XOffset), float64(offsetY+tileCache.YOffset))
|
||||
@ -156,30 +162,38 @@ func (v *Region) renderFloor(tile FloorShadowRecord, offsetX, offsetY int, targe
|
||||
}
|
||||
|
||||
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
|
||||
tileCacheIndex := (uint32(tile.MainIndex) << 16) | (uint32(tile.SubIndex) << 8) | (uint32(tile.Orientation))
|
||||
tileCache, exists := v.WallCache[tileCacheIndex]
|
||||
if !exists {
|
||||
v.WallCache[tileCacheIndex] = v.generateWallCache(tile)
|
||||
if v.WallCache[tileCacheIndex] == nil {
|
||||
log.Fatal("Could not generate wall")
|
||||
}
|
||||
tileCache = v.TileCache[tileCacheIndex]
|
||||
tileCache = v.WallCache[tileCacheIndex]
|
||||
}
|
||||
opts := &ebiten.DrawImageOptions{}
|
||||
opts.GeoM.Translate(float64(offsetX+tileCache.XOffset), float64(offsetY+tileCache.YOffset))
|
||||
target.DrawImage(tileCache.Image, opts)
|
||||
}
|
||||
|
||||
func (v *Region) decodeFloorData(blocks []Block, pixels []byte, tileYOffset int32, tileWidth int32) {
|
||||
func (v *Region) renderShadow(tile FloorShadowRecord, offsetX, offsetY int, target *ebiten.Image) {
|
||||
tileCacheIndex := (uint32(tile.MainIndex) << 16) + (uint32(tile.SubIndex) << 8) + 0
|
||||
tileCache, exists := v.ShadowCache[tileCacheIndex]
|
||||
if !exists {
|
||||
v.ShadowCache[tileCacheIndex] = v.generateShadowCache(tile)
|
||||
tileCache = v.ShadowCache[tileCacheIndex]
|
||||
if tileCache == nil {
|
||||
log.Fatal("Could not load shadow tile")
|
||||
}
|
||||
}
|
||||
opts := &ebiten.DrawImageOptions{}
|
||||
opts.GeoM.Translate(float64(offsetX+tileCache.XOffset), float64(offsetY+tileCache.YOffset))
|
||||
opts.ColorM = Common.ColorToColorM(color.RGBA{255, 255, 255, 160})
|
||||
target.DrawImage(tileCache.Image, opts)
|
||||
}
|
||||
|
||||
func (v *Region) decodeTileGfxData(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
|
||||
xjump := []int32{14, 12, 10, 8, 6, 4, 2, 0, 2, 4, 6, 8, 10, 12, 14}
|
||||
@ -198,12 +212,11 @@ func (v *Region) decodeFloorData(blocks []Block, pixels []byte, tileYOffset int3
|
||||
colorIndex := block.EncodedData[idx]
|
||||
if colorIndex != 0 {
|
||||
pixelColor := v.Palette.Colors[colorIndex]
|
||||
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)*tileWidth)+(blockX+x)))+3] = 0
|
||||
offset := 4 * (((blockY + y + tileYOffset) * tileWidth) + (blockX + x))
|
||||
pixels[offset] = pixelColor.R
|
||||
pixels[offset+1] = pixelColor.G
|
||||
pixels[offset+2] = pixelColor.B
|
||||
pixels[offset+3] = 255
|
||||
}
|
||||
x++
|
||||
n--
|
||||
@ -220,27 +233,27 @@ func (v *Region) decodeFloorData(blocks []Block, pixels []byte, tileYOffset int3
|
||||
idx := 0
|
||||
length := block.Length
|
||||
for length > 0 {
|
||||
length -= 2
|
||||
if (block.EncodedData[idx] + block.EncodedData[idx+1]) == 0 {
|
||||
x = 0
|
||||
y++
|
||||
idx += 2
|
||||
continue
|
||||
}
|
||||
length -= int32(block.EncodedData[idx+1])
|
||||
x += int32(block.EncodedData[idx])
|
||||
b1 := block.EncodedData[idx]
|
||||
b2 := block.EncodedData[idx+1]
|
||||
idx += 2
|
||||
length -= 2
|
||||
if (b1 | b2) == 0 {
|
||||
x = 0
|
||||
y++
|
||||
continue
|
||||
}
|
||||
x += int32(b1)
|
||||
length -= int32(b2)
|
||||
for b2 > 0 {
|
||||
colorIndex := block.EncodedData[idx]
|
||||
if colorIndex != 0 {
|
||||
pixelColor := v.Palette.Colors[colorIndex]
|
||||
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)*tileWidth)+(blockX+x)))+3] = 0
|
||||
offset := 4 * (((blockY + y + tileYOffset) * tileWidth) + (blockX + x))
|
||||
pixels[offset] = pixelColor.R
|
||||
pixels[offset+1] = pixelColor.G
|
||||
pixels[offset+2] = pixelColor.B
|
||||
pixels[offset+3] = 255
|
||||
|
||||
}
|
||||
idx++
|
||||
x++
|
||||
@ -254,7 +267,7 @@ func (v *Region) decodeFloorData(blocks []Block, pixels []byte, tileYOffset int3
|
||||
func (v *Region) generateFloorCache(tile FloorShadowRecord) *TileCacheRecord {
|
||||
tileData := v.getTile(int32(tile.MainIndex), int32(tile.SubIndex), 0)
|
||||
if tileData == nil {
|
||||
return nil
|
||||
log.Fatalf("Could not locate tile Idx:%d, Sub: %d, Ori: %d", tile.MainIndex, tile.SubIndex, 0)
|
||||
}
|
||||
tileYMinimum := int32(0)
|
||||
for _, block := range tileData.Blocks {
|
||||
@ -264,37 +277,73 @@ func (v *Region) generateFloorCache(tile FloorShadowRecord) *TileCacheRecord {
|
||||
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)
|
||||
v.decodeTileGfxData(tileData.Blocks, pixels, tileYOffset, tileData.Width)
|
||||
image.ReplacePixels(pixels)
|
||||
return &TileCacheRecord{image, 0, 0}
|
||||
}
|
||||
|
||||
func (v *Region) generateShadowCache(tile FloorShadowRecord) *TileCacheRecord {
|
||||
tileData := v.getTile(int32(tile.MainIndex), int32(tile.SubIndex), 13)
|
||||
if tileData == nil {
|
||||
return nil
|
||||
}
|
||||
tileMinY := int32(0)
|
||||
tileMaxY := int32(0)
|
||||
for _, block := range tileData.Blocks {
|
||||
tileMinY = Common.MinInt32(tileMinY, int32(block.Y))
|
||||
tileMaxY = Common.MaxInt32(tileMaxY, int32(block.Y+32))
|
||||
}
|
||||
tileYOffset := -tileMinY
|
||||
tileHeight := int(tileMaxY - tileMinY)
|
||||
image, _ := ebiten.NewImage(int(tileData.Width), int(tileHeight), ebiten.FilterNearest)
|
||||
pixels := make([]byte, 4*tileData.Width*int32(tileHeight))
|
||||
v.decodeTileGfxData(tileData.Blocks, pixels, tileYOffset, tileData.Width)
|
||||
image.ReplacePixels(pixels)
|
||||
return &TileCacheRecord{image, 0, int(tileMinY) + 80}
|
||||
}
|
||||
|
||||
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))
|
||||
var newTileData *Tile = nil
|
||||
if tile.Orientation == 3 {
|
||||
newTileData = v.getTile(int32(tile.MainIndex), int32(tile.SubIndex), int32(4))
|
||||
}
|
||||
|
||||
tileMinY := int32(0)
|
||||
tileMaxY := int32(0)
|
||||
target := tileData
|
||||
if newTileData != nil && newTileData.Height < tileData.Height {
|
||||
target = newTileData
|
||||
}
|
||||
for _, block := range target.Blocks {
|
||||
tileMinY = Common.MinInt32(tileMinY, int32(block.Y))
|
||||
tileMaxY = Common.MaxInt32(tileMaxY, int32(block.Y+32))
|
||||
}
|
||||
realHeight := Common.MaxInt32(Common.AbsInt32(tileData.Height), tileMaxY-tileMinY)
|
||||
tileYOffset := -tileMinY
|
||||
//tileHeight := int(tileMaxY - tileMinY)
|
||||
image, _ := ebiten.NewImage(160, int(realHeight), ebiten.FilterNearest)
|
||||
pixels := make([]byte, 4*160*realHeight)
|
||||
v.decodeTileGfxData(tileData.Blocks, pixels, tileYOffset, 160)
|
||||
if newTileData != nil {
|
||||
v.decodeTileGfxData(newTileData.Blocks, pixels, tileYOffset, 160)
|
||||
}
|
||||
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 {
|
||||
if tile.Orientation > 15 {
|
||||
// Lower Walls
|
||||
yAdjust = 80
|
||||
} else 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
|
||||
// Upper Walls, Special Tiles
|
||||
yAdjust = int(tileMinY) + 80
|
||||
}
|
||||
|
||||
image.ReplacePixels(pixels)
|
||||
return &TileCacheRecord{
|
||||
image,
|
||||
0,
|
||||
|
@ -13,9 +13,8 @@ type MapEngineTest struct {
|
||||
soundManager *Sound.Manager
|
||||
fileProvider Common.FileProvider
|
||||
sceneProvider SceneProvider
|
||||
//region *Map.Region
|
||||
gameState *Common.GameState
|
||||
mapEngine *Map.Engine
|
||||
gameState *Common.GameState
|
||||
mapEngine *Map.Engine
|
||||
}
|
||||
|
||||
func CreateMapEngineTest(
|
||||
@ -40,20 +39,19 @@ func (v *MapEngineTest) Load() []func() {
|
||||
return []func(){
|
||||
func() {
|
||||
v.mapEngine = Map.CreateMapEngine(v.gameState, v.soundManager, v.fileProvider)
|
||||
//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.RegionAct2Town, 301) // Broken rendering
|
||||
//v.mapEngine.GenerateMap(Map.RegionAct2Harem, 353)
|
||||
//v.mapEngine.GenerateMap(Map.RegionAct3Town, 529)
|
||||
//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.RegonAct5Town, 863)
|
||||
//v.mapEngine.GenerateMap(Map.RegionAct5IceCaves, 1038)
|
||||
//v.mapEngine.GenerateMap(Map.RegionAct5Siege, 879)
|
||||
//v.mapEngine.GenerateMap(Map.RegionAct5Lava, 1057) // PALETTE ISSUE
|
||||
// v.mapEngine.GenerateMap(Map.RegionAct2Town, 301) // Really broken rendering
|
||||
//v.mapEngine.GenerateMap(Map.RegionAct5Barricade, 880)
|
||||
|
||||
},
|
||||
}
|
||||
|
Loading…
Reference in New Issue
Block a user