mirror of
https://github.com/OpenDiablo2/OpenDiablo2
synced 2025-02-04 23:56:40 -05:00
Switcher with presets & better tiles randomizing (#173)
* tile choice algo * cycle region files * switcher limited by preset
This commit is contained in:
parent
7222f57c2c
commit
c3ba3f71e4
@ -181,7 +181,7 @@ func (v *MainMenu) Load() []func() {
|
||||
}
|
||||
|
||||
func (v *MainMenu) onMapTestClicked() {
|
||||
v.sceneProvider.SetNextScene(CreateMapEngineTest(v.fileProvider, v.sceneProvider, v.uiManager, v.soundManager, 0))
|
||||
v.sceneProvider.SetNextScene(CreateMapEngineTest(v.fileProvider, v.sceneProvider, v.uiManager, v.soundManager, 0, 1))
|
||||
}
|
||||
|
||||
func openbrowser(url string) {
|
||||
|
@ -21,6 +21,67 @@ import (
|
||||
"github.com/hajimehoshi/ebiten/inpututil"
|
||||
)
|
||||
|
||||
type RegionSpec struct {
|
||||
regionType d2enum.RegionIdType
|
||||
startPresetIndex int
|
||||
endPresetIndex int
|
||||
extra []int
|
||||
}
|
||||
|
||||
var regions []RegionSpec = []RegionSpec{
|
||||
//Act I
|
||||
{d2enum.RegionAct1Town, 1, 3, []int{}},
|
||||
{d2enum.RegionAct1Wilderness, 4, 52, []int{
|
||||
108,
|
||||
160, 161, 162, 163, 164,
|
||||
}},
|
||||
{d2enum.RegionAct1Cave, 53, 107, []int{}},
|
||||
{d2enum.RegionAct1Crypt, 109, 159, []int{}},
|
||||
{d2enum.RegionAct1Monestary, 165, 165, []int{}},
|
||||
{d2enum.RegionAct1Courtyard, 166, 166, []int{256}},
|
||||
{d2enum.RegionAct1Barracks, 167, 205, []int{}},
|
||||
{d2enum.RegionAct1Jail, 206, 255, []int{}},
|
||||
{d2enum.RegionAct1Cathedral, 257, 257, []int{}},
|
||||
{d2enum.RegionAct1Catacombs, 258, 299, []int{}},
|
||||
{d2enum.RegionAct1Tristram, 300, 300, []int{}},
|
||||
|
||||
//Act II
|
||||
{d2enum.RegionAct2Town, 301, 301, []int{}},
|
||||
{d2enum.RegionAct2Sewer, 302, 352, []int{}},
|
||||
{d2enum.RegionAct2Harem, 353, 357, []int{}},
|
||||
{d2enum.RegionAct2Basement, 358, 361, []int{}},
|
||||
{d2enum.RegionAct2Desert, 362, 413, []int{}},
|
||||
{d2enum.RegionAct2Tomb, 414, 481, []int{}},
|
||||
{d2enum.RegionAct2Lair, 482, 509, []int{}},
|
||||
{d2enum.RegionAct2Arcane, 510, 528, []int{}},
|
||||
|
||||
//Act III
|
||||
{d2enum.RegionAct3Town, 529, 529, []int{}},
|
||||
{d2enum.RegionAct3Jungle, 530, 604, []int{}},
|
||||
{d2enum.RegionAct3Kurast, 605, 658, []int{
|
||||
748, 749, 750, 751, 752, 753, 754,
|
||||
755, 756, 757, 758, 759, 760, 761, 762, 763, 764, 765, 766, 767, 768, 769, 770, 771, 772, 773, 774, 775, 776, 777, 778, 779, 780, 781, 782, 783, 784, 785, 786, 787, 788, 789, 790, 791, 792, 793, 794, 795, 796,
|
||||
//yeah, i know =(
|
||||
}},
|
||||
{d2enum.RegionAct3Spider, 659, 664, []int{}},
|
||||
{d2enum.RegionAct3Dungeon, 665, 704, []int{}},
|
||||
{d2enum.RegionAct3Sewer, 705, 747, []int{}},
|
||||
|
||||
//Act IV
|
||||
{d2enum.RegionAct4Town, 797, 798, []int{}},
|
||||
{d2enum.RegionAct4Mesa, 799, 835, []int{}},
|
||||
{d2enum.RegionAct4Lava, 836, 862, []int{}},
|
||||
|
||||
//Act V -- broken or wrong order
|
||||
{d2enum.RegonAct5Town, 863, 864, []int{}},
|
||||
{d2enum.RegionAct5Siege, 865, 879, []int{}},
|
||||
{d2enum.RegionAct5Barricade, 880, 1002, []int{}},
|
||||
{d2enum.RegionAct5IceCaves, 1003, 1041, []int{}},
|
||||
{d2enum.RegionAct5Temple, 1042, 1052, []int{}},
|
||||
{d2enum.RegionAct5Baal, 1059, 1090, []int{}},
|
||||
{d2enum.RegionAct5Lava, 1053, 1058, []int{}},
|
||||
}
|
||||
|
||||
type MapEngineTest struct {
|
||||
uiManager *d2ui.Manager
|
||||
soundManager *d2audio.Manager
|
||||
@ -28,8 +89,15 @@ type MapEngineTest struct {
|
||||
sceneProvider d2coreinterface.SceneProvider
|
||||
gameState *d2core.GameState
|
||||
mapEngine *_map.Engine
|
||||
|
||||
//TODO: this is region specific properties, should be refactored for multi-region rendering
|
||||
currentRegion int
|
||||
keyLocked bool
|
||||
levelPreset int
|
||||
fileIndex int
|
||||
regionSpec RegionSpec
|
||||
filesCount int
|
||||
|
||||
keyLocked bool
|
||||
}
|
||||
|
||||
func CreateMapEngineTest(
|
||||
@ -37,50 +105,56 @@ func CreateMapEngineTest(
|
||||
sceneProvider d2coreinterface.SceneProvider,
|
||||
uiManager *d2ui.Manager,
|
||||
soundManager *d2audio.Manager,
|
||||
currentRegion int) *MapEngineTest {
|
||||
currentRegion int, levelPreset int) *MapEngineTest {
|
||||
result := &MapEngineTest{
|
||||
fileProvider: fileProvider,
|
||||
uiManager: uiManager,
|
||||
soundManager: soundManager,
|
||||
sceneProvider: sceneProvider,
|
||||
currentRegion: currentRegion,
|
||||
levelPreset: levelPreset,
|
||||
fileIndex: -1,
|
||||
regionSpec: RegionSpec{},
|
||||
filesCount: 0,
|
||||
keyLocked: false,
|
||||
}
|
||||
result.gameState = d2core.CreateTestGameState()
|
||||
return result
|
||||
}
|
||||
|
||||
type RegionSpec struct {
|
||||
regionType d2enum.RegionIdType
|
||||
levelPreset int
|
||||
}
|
||||
func (v *MapEngineTest) LoadRegionByIndex(n int, levelPreset, fileIndex int) {
|
||||
for _, spec := range regions {
|
||||
if spec.regionType == d2enum.RegionIdType(n) {
|
||||
v.regionSpec = spec
|
||||
inExtra := false
|
||||
for _, e := range spec.extra {
|
||||
if e == levelPreset {
|
||||
inExtra = true
|
||||
break
|
||||
}
|
||||
}
|
||||
if !inExtra {
|
||||
if levelPreset < spec.startPresetIndex {
|
||||
levelPreset = spec.startPresetIndex
|
||||
}
|
||||
|
||||
var regions []RegionSpec = []RegionSpec{
|
||||
{d2enum.RegionAct1Tristram, 300},
|
||||
{d2enum.RegionAct1Cathedral, 257},
|
||||
{d2enum.RegionAct2Town, 301},
|
||||
// {d2enum.RegionAct2Harem, 353},
|
||||
{d2enum.RegionAct3Town, 529},
|
||||
{d2enum.RegionAct3Jungle, 574},
|
||||
{d2enum.RegionAct4Town, 797},
|
||||
{d2enum.RegonAct5Town, 863},
|
||||
{d2enum.RegionAct5IceCaves, 1038},
|
||||
{d2enum.RegionAct5Siege, 879},
|
||||
{d2enum.RegionAct5Lava, 105},
|
||||
{d2enum.RegionAct5Barricade, 880},
|
||||
}
|
||||
if levelPreset > spec.endPresetIndex {
|
||||
levelPreset = spec.endPresetIndex
|
||||
}
|
||||
}
|
||||
v.levelPreset = levelPreset
|
||||
}
|
||||
}
|
||||
|
||||
func (v *MapEngineTest) LoadRegionByIndex(n int) {
|
||||
if n == 0 {
|
||||
v.mapEngine.GenerateAct1Overworld()
|
||||
return
|
||||
}
|
||||
region := regions[n-1]
|
||||
|
||||
v.mapEngine = _map.CreateMapEngine(v.gameState, v.soundManager, v.fileProvider) // necessary for map name update
|
||||
v.mapEngine.OffsetY = 0
|
||||
v.mapEngine.OffsetX = 0
|
||||
v.mapEngine.GenerateMap(region.regionType, region.levelPreset)
|
||||
v.mapEngine.GenerateMap(d2enum.RegionIdType(n), levelPreset, fileIndex)
|
||||
}
|
||||
|
||||
func (v *MapEngineTest) Load() []func() {
|
||||
@ -91,21 +165,7 @@ func (v *MapEngineTest) Load() []func() {
|
||||
func() {
|
||||
v.mapEngine = _map.CreateMapEngine(v.gameState, v.soundManager, v.fileProvider)
|
||||
|
||||
v.LoadRegionByIndex(v.currentRegion)
|
||||
// v.mapEngine.GenerateAct1Overworld()
|
||||
// v.mapEngine.GenerateMap(d2enum.RegionAct1Tristram, 300)
|
||||
// v.mapEngine.GenerateMap(d2enum.RegionAct1Cathedral, 257)
|
||||
//v.mapEngine.GenerateMap(d2enum.RegionAct2Town, 301)
|
||||
//v.mapEngine.GenerateMap(d2enum.RegionAct2Harem, 353) // Crashes on dcc load
|
||||
//v.mapEngine.GenerateMap(d2enum.RegionAct3Town, 529)
|
||||
//v.mapEngine.GenerateMap(d2enum.RegionAct3Jungle, 574)
|
||||
//v.mapEngine.GenerateMap(d2enum.RegionAct4Town, 797) // Broken height of large objects
|
||||
//v.mapEngine.GenerateMap(d2enum.RegonAct5Town, 863) // Completely broken!!
|
||||
//v.mapEngine.GenerateMap(d2enum.RegionAct5IceCaves, 1038) // Completely broken!
|
||||
//v.mapEngine.GenerateMap(d2enum.RegionAct5Siege, 879) // Completely broken!
|
||||
//v.mapEngine.GenerateMap(d2enum.RegionAct5Lava, 1057) // Broken
|
||||
//v.mapEngine.GenerateMap(d2enum.RegionAct5Barricade, 880) // Broken
|
||||
|
||||
v.LoadRegionByIndex(v.currentRegion, v.levelPreset, v.fileIndex)
|
||||
},
|
||||
}
|
||||
}
|
||||
@ -133,13 +193,34 @@ func (v *MapEngineTest) Render(screen *ebiten.Image) {
|
||||
int(math.Ceil(tileY))-curRegion.Rect.Top,
|
||||
subtileY,
|
||||
)
|
||||
|
||||
levelFilesToPick := make([]string, 0)
|
||||
fileIndex := v.fileIndex
|
||||
for n, fileRecord := range curRegion.Region.LevelPreset.Files {
|
||||
if len(fileRecord) == 0 || fileRecord == "" || fileRecord == "0" {
|
||||
continue
|
||||
}
|
||||
levelFilesToPick = append(levelFilesToPick, fileRecord)
|
||||
if fileRecord == curRegion.Region.RegionPath {
|
||||
fileIndex = n
|
||||
}
|
||||
}
|
||||
if v.fileIndex == -1 {
|
||||
v.fileIndex = fileIndex
|
||||
}
|
||||
v.filesCount = len(levelFilesToPick)
|
||||
ebitenutil.DebugPrintAt(screen, line, 5, 5)
|
||||
ebitenutil.DebugPrintAt(screen, "Map: "+curRegion.Region.LevelType.Name, 5, 17)
|
||||
ebitenutil.DebugPrintAt(screen, fmt.Sprintf("%v [%v]", curRegion.Region.RegionPath, v.currentRegion), 5, 29)
|
||||
ebitenutil.DebugPrintAt(screen, "N - next map, P - previous map", 5, 41)
|
||||
ebitenutil.DebugPrintAt(screen, fmt.Sprintf("%v: %v/%v [%v, %v]", curRegion.Region.RegionPath, fileIndex+1, v.filesCount, v.currentRegion, v.levelPreset), 5, 29)
|
||||
ebitenutil.DebugPrintAt(screen, "N - next region, P - previous region", 5, 41)
|
||||
ebitenutil.DebugPrintAt(screen, "Shift+N - next preset, Shift+P - previous preset", 5, 53)
|
||||
ebitenutil.DebugPrintAt(screen, "Ctrl+N - next file, Ctrl+P - previous file", 5, 65)
|
||||
}
|
||||
|
||||
func (v *MapEngineTest) Update(tickTime float64) {
|
||||
ctrlPressed := v.uiManager.KeyPressed(ebiten.KeyControl)
|
||||
shiftPressed := v.uiManager.KeyPressed(ebiten.KeyShift)
|
||||
|
||||
if v.uiManager.KeyPressed(ebiten.KeyDown) {
|
||||
v.mapEngine.OffsetY -= tickTime * 800
|
||||
}
|
||||
@ -164,26 +245,50 @@ func (v *MapEngineTest) Update(tickTime float64) {
|
||||
if v.uiManager.KeyPressed(ebiten.KeyEscape) {
|
||||
os.Exit(0)
|
||||
}
|
||||
if v.uiManager.KeyPressed(ebiten.KeyN) && !v.keyLocked {
|
||||
v.currentRegion++
|
||||
if v.currentRegion == len(regions) {
|
||||
v.currentRegion = 0
|
||||
}
|
||||
v.keyLocked = true
|
||||
fmt.Println("---")
|
||||
v.sceneProvider.SetNextScene(v)
|
||||
return
|
||||
}
|
||||
|
||||
if v.uiManager.KeyPressed(ebiten.KeyP) && !v.keyLocked {
|
||||
v.currentRegion--
|
||||
if v.currentRegion == -1 {
|
||||
v.currentRegion = len(regions) - 1
|
||||
if !v.keyLocked {
|
||||
|
||||
if v.uiManager.KeyPressed(ebiten.KeyN) && ctrlPressed {
|
||||
v.fileIndex = increment(v.fileIndex, 0, v.filesCount-1)
|
||||
v.keyLocked = true
|
||||
v.sceneProvider.SetNextScene(v)
|
||||
return
|
||||
}
|
||||
|
||||
if v.uiManager.KeyPressed(ebiten.KeyP) && ctrlPressed {
|
||||
v.fileIndex = decrement(v.fileIndex, 0, v.filesCount-1)
|
||||
v.keyLocked = true
|
||||
v.sceneProvider.SetNextScene(v)
|
||||
return
|
||||
}
|
||||
|
||||
if v.uiManager.KeyPressed(ebiten.KeyN) && shiftPressed {
|
||||
v.levelPreset = increment(v.levelPreset, v.regionSpec.startPresetIndex, v.regionSpec.endPresetIndex)
|
||||
v.keyLocked = true
|
||||
v.sceneProvider.SetNextScene(v)
|
||||
return
|
||||
}
|
||||
|
||||
if v.uiManager.KeyPressed(ebiten.KeyP) && shiftPressed {
|
||||
v.levelPreset = decrement(v.levelPreset, v.regionSpec.startPresetIndex, v.regionSpec.endPresetIndex)
|
||||
v.keyLocked = true
|
||||
v.sceneProvider.SetNextScene(v)
|
||||
return
|
||||
}
|
||||
|
||||
if v.uiManager.KeyPressed(ebiten.KeyN) {
|
||||
v.currentRegion = increment(v.currentRegion, 0, len(regions))
|
||||
v.keyLocked = true
|
||||
v.sceneProvider.SetNextScene(v)
|
||||
return
|
||||
}
|
||||
|
||||
if v.uiManager.KeyPressed(ebiten.KeyP) {
|
||||
v.currentRegion = decrement(v.currentRegion, 0, len(regions))
|
||||
v.keyLocked = true
|
||||
v.sceneProvider.SetNextScene(v)
|
||||
return
|
||||
}
|
||||
v.keyLocked = true
|
||||
fmt.Println("---")
|
||||
v.sceneProvider.SetNextScene(v)
|
||||
return
|
||||
}
|
||||
|
||||
//FIXME: do it better
|
||||
@ -191,3 +296,19 @@ func (v *MapEngineTest) Update(tickTime float64) {
|
||||
v.keyLocked = false
|
||||
}
|
||||
}
|
||||
|
||||
func increment(v, min, max int) int {
|
||||
v++
|
||||
if v > max {
|
||||
return min
|
||||
}
|
||||
return v
|
||||
}
|
||||
|
||||
func decrement(v, min, max int) int {
|
||||
v--
|
||||
if v < min {
|
||||
return max
|
||||
}
|
||||
return v
|
||||
}
|
||||
|
@ -214,6 +214,9 @@ func (v *AnimatedEntity) cacheFrames(layerName string) {
|
||||
}
|
||||
|
||||
direction := dcc.Directions[v.direction]
|
||||
if frameIndex >= len(direction.Frames) {
|
||||
continue
|
||||
}
|
||||
frame := direction.Frames[frameIndex]
|
||||
img := image.NewRGBA(image.Rect(0, 0, int(frameW), int(frameH)))
|
||||
for y := 0; y < direction.Box.Height; y++ {
|
||||
|
@ -52,9 +52,10 @@ func CreateMapEngine(gameState *d2core.GameState, soundManager *d2audio.Manager,
|
||||
return result
|
||||
}
|
||||
|
||||
func (v *Engine) GenerateMap(regionType d2enum.RegionIdType, levelPreset int) {
|
||||
func (v *Engine) GenerateMap(regionType d2enum.RegionIdType, levelPreset int, fileIndex int) {
|
||||
randomSource := rand.NewSource(v.gameState.Seed)
|
||||
region := LoadRegion(randomSource, regionType, levelPreset, v.fileProvider)
|
||||
region := LoadRegion(randomSource, regionType, levelPreset, v.fileProvider, fileIndex)
|
||||
fmt.Printf("Loading region: %v\n", region.RegionPath)
|
||||
v.regions = append(v.regions, EngineRegion{
|
||||
Rect: d2common.Rectangle{0, 0, int(region.TileWidth), int(region.TileHeight)},
|
||||
Region: region,
|
||||
@ -68,19 +69,19 @@ func (v *Engine) GenerateMap(regionType d2enum.RegionIdType, levelPreset int) {
|
||||
func (v *Engine) GenerateAct1Overworld() {
|
||||
v.soundManager.PlayBGM("/data/global/music/Act1/town1.wav") // TODO: Temp stuff here
|
||||
randomSource := rand.NewSource(v.gameState.Seed)
|
||||
region := LoadRegion(randomSource, d2enum.RegionAct1Town, 1, v.fileProvider)
|
||||
region := LoadRegion(randomSource, d2enum.RegionAct1Town, 1, v.fileProvider, -1)
|
||||
v.regions = append(v.regions, EngineRegion{
|
||||
Rect: d2common.Rectangle{0, 0, int(region.TileWidth), int(region.TileHeight)},
|
||||
Region: region,
|
||||
})
|
||||
if strings.Contains(region.RegionPath, "E1") {
|
||||
region2 := LoadRegion(randomSource, d2enum.RegionAct1Town, 2, v.fileProvider)
|
||||
region2 := LoadRegion(randomSource, d2enum.RegionAct1Town, 2, v.fileProvider, -1)
|
||||
v.regions = append(v.regions, EngineRegion{
|
||||
Rect: d2common.Rectangle{int(region.TileWidth - 1), 0, int(region2.TileWidth), int(region2.TileHeight)},
|
||||
Region: region2,
|
||||
})
|
||||
} else if strings.Contains(region.RegionPath, "S1") {
|
||||
region2 := LoadRegion(randomSource, d2enum.RegionAct1Town, 3, v.fileProvider)
|
||||
region2 := LoadRegion(randomSource, d2enum.RegionAct1Town, 3, v.fileProvider, -1)
|
||||
v.regions = append(v.regions, EngineRegion{
|
||||
Rect: d2common.Rectangle{0, int(region.TileHeight - 1), int(region2.TileWidth), int(region2.TileHeight)},
|
||||
Region: region2,
|
||||
|
@ -1,12 +1,15 @@
|
||||
package d2mapengine
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
"image/color"
|
||||
"log"
|
||||
"math"
|
||||
"math/rand"
|
||||
"sort"
|
||||
"strconv"
|
||||
"sync"
|
||||
"time"
|
||||
|
||||
"github.com/OpenDiablo2/D2Shared/d2data/d2dt1"
|
||||
|
||||
@ -30,32 +33,39 @@ import (
|
||||
"github.com/hajimehoshi/ebiten"
|
||||
)
|
||||
|
||||
//TODO: move to corresponding file
|
||||
type ByRarity []d2dt1.Tile
|
||||
|
||||
func (a ByRarity) Len() int { return len(a) }
|
||||
func (a ByRarity) Less(i, j int) bool { return a[i].RarityFrameIndex < a[j].RarityFrameIndex }
|
||||
func (a ByRarity) Swap(i, j int) { a[i], a[j] = a[j], a[i] }
|
||||
|
||||
type Region struct {
|
||||
RegionPath string
|
||||
LevelType d2datadict.LevelTypeRecord
|
||||
levelPreset d2datadict.LevelPresetRecord
|
||||
LevelPreset d2datadict.LevelPresetRecord
|
||||
TileWidth int32
|
||||
TileHeight int32
|
||||
Tiles []d2dt1.Tile
|
||||
DS1 d2ds1.DS1
|
||||
Palette d2datadict.PaletteRec
|
||||
FloorCache map[uint32]*TileCacheRecord
|
||||
ShadowCache map[uint32]*TileCacheRecord
|
||||
WallCache map[uint32]*TileCacheRecord
|
||||
FloorCache map[string]*TileCacheRecord
|
||||
ShadowCache map[string]*TileCacheRecord
|
||||
WallCache map[string]*TileCacheRecord
|
||||
AnimationEntities []d2render.AnimatedEntity
|
||||
NPCs []*d2core.NPC
|
||||
StartX float64
|
||||
StartY float64
|
||||
}
|
||||
|
||||
func LoadRegion(seed rand.Source, levelType d2enum.RegionIdType, levelPreset int, fileProvider d2interface.FileProvider) *Region {
|
||||
func LoadRegion(seed rand.Source, levelType d2enum.RegionIdType, levelPreset int, fileProvider d2interface.FileProvider, fileIndex int) *Region {
|
||||
result := &Region{
|
||||
LevelType: d2datadict.LevelTypes[levelType],
|
||||
levelPreset: d2datadict.LevelPresets[levelPreset],
|
||||
LevelPreset: d2datadict.LevelPresets[levelPreset],
|
||||
Tiles: make([]d2dt1.Tile, 0),
|
||||
FloorCache: make(map[uint32]*TileCacheRecord),
|
||||
ShadowCache: make(map[uint32]*TileCacheRecord),
|
||||
WallCache: make(map[uint32]*TileCacheRecord),
|
||||
FloorCache: make(map[string]*TileCacheRecord),
|
||||
ShadowCache: make(map[string]*TileCacheRecord),
|
||||
WallCache: make(map[string]*TileCacheRecord),
|
||||
}
|
||||
result.Palette = d2datadict.Palettes[d2enum.PaletteType("act"+strconv.Itoa(int(result.LevelType.Act)))]
|
||||
//bm := result.levelPreset.Dt1Mask
|
||||
@ -74,7 +84,7 @@ func LoadRegion(seed rand.Source, levelType d2enum.RegionIdType, levelPreset int
|
||||
result.Tiles = append(result.Tiles, dt1.Tiles...)
|
||||
}
|
||||
levelFilesToPick := make([]string, 0)
|
||||
for _, fileRecord := range result.levelPreset.Files {
|
||||
for _, fileRecord := range result.LevelPreset.Files {
|
||||
if len(fileRecord) == 0 || fileRecord == "" || fileRecord == "0" {
|
||||
continue
|
||||
}
|
||||
@ -82,6 +92,9 @@ func LoadRegion(seed rand.Source, levelType d2enum.RegionIdType, levelPreset int
|
||||
}
|
||||
random := rand.New(seed)
|
||||
levelIndex := int(math.Round(float64(len(levelFilesToPick)-1) * random.Float64()))
|
||||
if fileIndex >= 0 && fileIndex < len(levelFilesToPick) {
|
||||
levelIndex = fileIndex
|
||||
}
|
||||
levelFile := levelFilesToPick[levelIndex]
|
||||
result.RegionPath = levelFile
|
||||
result.DS1 = d2ds1.LoadDS1("/data/global/tiles/"+levelFile, fileProvider)
|
||||
@ -125,59 +138,86 @@ func (v *Region) RenderTile(offsetX, offsetY, tileX, tileY int, layerType d2enum
|
||||
offsetX -= 80
|
||||
switch layerType {
|
||||
case d2enum.RegionLayerTypeFloors:
|
||||
v.renderFloor(v.DS1.Tiles[tileY][tileX].Floors[layerIndex], offsetX, offsetY, target)
|
||||
v.renderFloor(v.DS1.Tiles[tileY][tileX].Floors[layerIndex], offsetX, offsetY, target, tileX, tileY)
|
||||
case d2enum.RegionLayerTypeWalls:
|
||||
v.renderWall(v.DS1.Tiles[tileY][tileX].Walls[layerIndex], offsetX, offsetY, target)
|
||||
v.renderWall(v.DS1.Tiles[tileY][tileX].Walls[layerIndex], offsetX, offsetY, target, tileX, tileY)
|
||||
case d2enum.RegionLayerTypeShadows:
|
||||
v.renderShadow(v.DS1.Tiles[tileY][tileX].Shadows[layerIndex], offsetX, offsetY, target)
|
||||
v.renderShadow(v.DS1.Tiles[tileY][tileX].Shadows[layerIndex], offsetX, offsetY, target, tileX, tileY)
|
||||
}
|
||||
}
|
||||
|
||||
func (v *Region) getRandomTile(tiles []d2dt1.Tile) *d2dt1.Tile {
|
||||
if len(tiles) == 1 {
|
||||
return &tiles[0]
|
||||
}
|
||||
sort.Sort(ByRarity(tiles))
|
||||
s := 0
|
||||
for _, t := range tiles {
|
||||
s += int(t.RarityFrameIndex)
|
||||
}
|
||||
rand.Seed(time.Now().UnixNano())
|
||||
r := 0
|
||||
if s != 0 {
|
||||
r = rand.Intn(s) + 1
|
||||
}
|
||||
for _, t := range tiles {
|
||||
r -= int(t.RarityFrameIndex)
|
||||
if r <= 0 {
|
||||
return &t
|
||||
}
|
||||
}
|
||||
return &tiles[0]
|
||||
}
|
||||
|
||||
func (v *Region) getTile(mainIndex, subIndex, orientation int32) *d2dt1.Tile {
|
||||
// TODO: Need to support randomly grabbing tile based on x/y as there can be multiple matches for same main/sub index
|
||||
tiles := []d2dt1.Tile{}
|
||||
for _, tile := range v.Tiles {
|
||||
if tile.MainIndex != mainIndex || tile.SubIndex != subIndex || tile.Orientation != orientation {
|
||||
continue
|
||||
}
|
||||
return &tile
|
||||
tiles = append(tiles, tile)
|
||||
}
|
||||
//log.Fatalf("Unknown tile ID [%d %d %d]", mainIndex, subIndex, orientation)
|
||||
return nil
|
||||
if len(tiles) == 0 {
|
||||
log.Printf("Unknown tile ID [%d %d %d]\n", mainIndex, subIndex, orientation)
|
||||
return nil
|
||||
}
|
||||
return v.getRandomTile(tiles)
|
||||
}
|
||||
|
||||
func (v *Region) renderFloor(tile d2ds1.FloorShadowRecord, offsetX, offsetY int, target *ebiten.Image) {
|
||||
tileCacheIndex := (uint32(tile.MainIndex) << 16) | (uint32(tile.SubIndex) << 8)
|
||||
func (v *Region) renderFloor(tile d2ds1.FloorShadowRecord, offsetX, offsetY int, target *ebiten.Image, tileX, tileY int) {
|
||||
tileCacheIndex := fmt.Sprintf("%v-%v-%v-%v", tileY, tileX, tile.MainIndex, tile.SubIndex)
|
||||
tileCache, exists := v.FloorCache[tileCacheIndex]
|
||||
if !exists {
|
||||
v.FloorCache[tileCacheIndex] = v.generateFloorCache(tile)
|
||||
tileCache = v.FloorCache[tileCacheIndex]
|
||||
if tileCache == nil {
|
||||
log.Println("Could not load floor tile")
|
||||
log.Println("Could not load floor tile: " + tileCacheIndex)
|
||||
return
|
||||
}
|
||||
}
|
||||
if tileCache == nil {
|
||||
log.Println("Nil tile cache")
|
||||
log.Println("Nil tile cache: " + tileCacheIndex)
|
||||
return
|
||||
}
|
||||
opts := &ebiten.DrawImageOptions{}
|
||||
opts.GeoM.Translate(float64(offsetX+tileCache.XOffset), float64(offsetY+tileCache.YOffset))
|
||||
target.DrawImage(tileCache.Image, opts)
|
||||
return
|
||||
}
|
||||
|
||||
func (v *Region) renderWall(tile d2ds1.WallRecord, offsetX, offsetY int, target *ebiten.Image) {
|
||||
tileCacheIndex := (uint32(tile.MainIndex) << 16) | (uint32(tile.SubIndex) << 8) | (uint32(tile.Orientation))
|
||||
func (v *Region) renderWall(tile d2ds1.WallRecord, offsetX, offsetY int, target *ebiten.Image, tileX, tileY int) {
|
||||
tileCacheIndex := fmt.Sprintf("%v-%v-%v-%v-%v", tileY, tileX, tile.MainIndex, tile.SubIndex, tile.Orientation)
|
||||
tileCache, exists := v.WallCache[tileCacheIndex]
|
||||
if !exists {
|
||||
v.WallCache[tileCacheIndex] = v.generateWallCache(tile)
|
||||
if v.WallCache[tileCacheIndex] == nil {
|
||||
log.Println("Could not generate wall")
|
||||
log.Println("Could not generate wall: " + tileCacheIndex)
|
||||
return
|
||||
}
|
||||
tileCache = v.WallCache[tileCacheIndex]
|
||||
}
|
||||
if tileCache == nil {
|
||||
log.Println("Nil tile cache")
|
||||
log.Println("Nil tile cache: " + tileCacheIndex)
|
||||
return
|
||||
}
|
||||
opts := &ebiten.DrawImageOptions{}
|
||||
@ -185,19 +225,19 @@ func (v *Region) renderWall(tile d2ds1.WallRecord, offsetX, offsetY int, target
|
||||
target.DrawImage(tileCache.Image, opts)
|
||||
}
|
||||
|
||||
func (v *Region) renderShadow(tile d2ds1.FloorShadowRecord, offsetX, offsetY int, target *ebiten.Image) {
|
||||
tileCacheIndex := (uint32(tile.MainIndex) << 16) + (uint32(tile.SubIndex) << 8) + 0
|
||||
func (v *Region) renderShadow(tile d2ds1.FloorShadowRecord, offsetX, offsetY int, target *ebiten.Image, tileX, tileY int) {
|
||||
tileCacheIndex := fmt.Sprintf("%v-%v-%v-%v", tileY, tileX, tile.MainIndex, tile.SubIndex)
|
||||
tileCache, exists := v.ShadowCache[tileCacheIndex]
|
||||
if !exists {
|
||||
v.ShadowCache[tileCacheIndex] = v.generateShadowCache(tile)
|
||||
tileCache = v.ShadowCache[tileCacheIndex]
|
||||
if tileCache == nil {
|
||||
log.Println("Could not load shadow tile")
|
||||
log.Println("Could not load shadow tile: " + tileCacheIndex)
|
||||
return
|
||||
}
|
||||
}
|
||||
if tileCache == nil {
|
||||
log.Println("Nil tile cache")
|
||||
log.Println("Nil tile cache: " + tileCacheIndex)
|
||||
return
|
||||
}
|
||||
opts := &ebiten.DrawImageOptions{}
|
||||
|
5
go.mod
5
go.mod
@ -3,6 +3,10 @@ module github.com/OpenDiablo2/OpenDiablo2
|
||||
go 1.12
|
||||
|
||||
require (
|
||||
github.com/JoshVarga/blast v0.0.0-20180421040937-681c804fb9f0
|
||||
github.com/alecthomas/template v0.0.0-20190718012654-fb15b899a751 // indirect
|
||||
github.com/alecthomas/units v0.0.0-20190924025748-f65c72e2690d // indirect
|
||||
github.com/hajimehoshi/ebiten v1.11.0-alpha.0.20191115171053-e42cff071c36
|
||||
github.com/OpenDiablo2/D2Shared v0.0.0-20191117044836-c56c888bec7d
|
||||
github.com/hajimehoshi/ebiten v1.11.0-alpha.0.20191116200143-acc933b7c399
|
||||
github.com/hajimehoshi/oto v0.5.3 // indirect
|
||||
@ -10,4 +14,5 @@ require (
|
||||
golang.org/x/exp v0.0.0-20191030013958-a1ab85dbe136 // indirect
|
||||
golang.org/x/mobile v0.0.0-20191115022231-f0c40035f2ba // indirect
|
||||
golang.org/x/sys v0.0.0-20191115151921-52ab43148777 // indirect
|
||||
gopkg.in/alecthomas/kingpin.v2 v2.2.6
|
||||
)
|
||||
|
11
main.go
11
main.go
@ -13,6 +13,7 @@ import (
|
||||
"github.com/OpenDiablo2/OpenDiablo2/d2core"
|
||||
"github.com/OpenDiablo2/D2Shared/d2data/d2mpq"
|
||||
"github.com/hajimehoshi/ebiten"
|
||||
"gopkg.in/alecthomas/kingpin.v2"
|
||||
)
|
||||
|
||||
// GitBranch is set by the CI build process to the name of the branch
|
||||
@ -22,6 +23,9 @@ var GitBranch string
|
||||
var GitCommit string
|
||||
var d2Engine d2core.Engine
|
||||
|
||||
var region = kingpin.Arg("region", "Region type id").Int()
|
||||
var preset = kingpin.Arg("preset", "Level preset").Int()
|
||||
|
||||
func main() {
|
||||
//defer profile.Start(profile.CPUProfile).Stop()
|
||||
//runtime.LockOSThread()
|
||||
@ -39,7 +43,12 @@ func main() {
|
||||
}
|
||||
d2mpq.InitializeCryptoBuffer()
|
||||
d2Engine = d2core.CreateEngine()
|
||||
d2Engine.SetNextScene(d2scene.CreateMainMenu(&d2Engine, &d2Engine, d2Engine.UIManager, d2Engine.SoundManager))
|
||||
kingpin.Parse()
|
||||
if *region == 0 {
|
||||
d2Engine.SetNextScene(d2scene.CreateMainMenu(&d2Engine, &d2Engine, d2Engine.UIManager, d2Engine.SoundManager))
|
||||
} else {
|
||||
d2Engine.SetNextScene(d2scene.CreateMapEngineTest(&d2Engine, &d2Engine, d2Engine.UIManager, d2Engine.SoundManager, *region, *preset))
|
||||
}
|
||||
ebiten.SetCursorVisible(false)
|
||||
ebiten.SetFullscreen(d2Engine.Settings.FullScreen)
|
||||
ebiten.SetRunnableInBackground(d2Engine.Settings.RunInBackground)
|
||||
|
Loading…
Reference in New Issue
Block a user