mirror of
https://github.com/OpenDiablo2/OpenDiablo2
synced 2025-02-04 23:56:40 -05:00
Added object support (#93)
* Fixed LevelTypes load * Update ResourcePaths.go * Added DCC loading support * Added animation data. Fixed bitshift version compile issue. * Fixed another go build error * Initial support for object rendering
This commit is contained in:
parent
2ec5dd2d85
commit
01a48d8720
125
Common/AnimatedEntity.go
Normal file
125
Common/AnimatedEntity.go
Normal file
@ -0,0 +1,125 @@
|
||||
package Common
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
"strings"
|
||||
"time"
|
||||
|
||||
"github.com/OpenDiablo2/OpenDiablo2/PaletteDefs"
|
||||
|
||||
"github.com/hajimehoshi/ebiten"
|
||||
)
|
||||
|
||||
type AnimatedEntity struct {
|
||||
dcc *DCC
|
||||
cof *Cof
|
||||
palette PaletteDefs.PaletteType
|
||||
base string
|
||||
token string
|
||||
tr string
|
||||
animationMode string
|
||||
weaponClass string
|
||||
lastFrameTime time.Time
|
||||
framesToAnimate int
|
||||
animationSpeed int
|
||||
direction int
|
||||
currentFrame int
|
||||
LocationX float64
|
||||
LocationY float64
|
||||
frames []*ebiten.Image
|
||||
frameLocations []Rectangle
|
||||
}
|
||||
|
||||
func CreateAnimatedEntity(base, token, tr string, palette PaletteDefs.PaletteType) *AnimatedEntity {
|
||||
result := &AnimatedEntity{
|
||||
base: base,
|
||||
token: token,
|
||||
tr: tr,
|
||||
palette: palette,
|
||||
}
|
||||
return result
|
||||
}
|
||||
|
||||
var DirectionLookup = []int{3, 15, 4, 8, 0, 9, 5, 10, 1, 11, 6, 12, 2, 13, 7, 14}
|
||||
|
||||
func (v *AnimatedEntity) SetMode(animationMode, weaponClass string, direction int, provider FileProvider) {
|
||||
dccPath := fmt.Sprintf("%s/%s/tr/%str%s%s%s.dcc", v.base, v.token, v.token, v.tr, animationMode, weaponClass)
|
||||
v.dcc = LoadDCC(dccPath, provider)
|
||||
cofPath := fmt.Sprintf("%s/%s/cof/%s%s%s.cof", v.base, v.token, v.token, animationMode, weaponClass)
|
||||
v.cof = LoadCof(cofPath, provider)
|
||||
v.animationMode = animationMode
|
||||
v.weaponClass = weaponClass
|
||||
v.direction = direction
|
||||
v.cacheFrames()
|
||||
}
|
||||
|
||||
func (v *AnimatedEntity) Render(target *ebiten.Image, offsetX, offsetY int) {
|
||||
for v.lastFrameTime.Add(time.Millisecond * time.Duration(v.animationSpeed)).Before(time.Now()) {
|
||||
v.lastFrameTime = v.lastFrameTime.Add(time.Millisecond * time.Duration(v.animationSpeed))
|
||||
v.currentFrame++
|
||||
if v.currentFrame >= v.framesToAnimate {
|
||||
v.currentFrame = 0
|
||||
}
|
||||
}
|
||||
|
||||
opts := &ebiten.DrawImageOptions{}
|
||||
opts.GeoM.Translate(float64(v.frameLocations[v.currentFrame].Left+offsetX), float64(v.frameLocations[v.currentFrame].Top+offsetY+40))
|
||||
target.DrawImage(v.frames[v.currentFrame], opts)
|
||||
}
|
||||
|
||||
func (v *AnimatedEntity) cacheFrames() {
|
||||
animationData := AnimationData[strings.ToLower(v.token+v.animationMode+v.weaponClass)][v.direction]
|
||||
v.animationSpeed = int((float64(animationData.AnimationSpeed) / 255.0) * 0.04 * 1000.0)
|
||||
v.framesToAnimate = animationData.FramesPerDirection
|
||||
v.lastFrameTime = time.Now()
|
||||
minX := int32(2147483647)
|
||||
minY := int32(2147483647)
|
||||
maxX := int32(-2147483648)
|
||||
maxY := int32(-2147483648)
|
||||
for _, layer := range v.dcc.Directions {
|
||||
minX = MinInt32(minX, int32(layer.Box.Left))
|
||||
minY = MinInt32(minY, int32(layer.Box.Top))
|
||||
maxX = MaxInt32(maxX, int32(layer.Box.Right()))
|
||||
maxY = MaxInt32(maxY, int32(layer.Box.Bottom()))
|
||||
}
|
||||
frameW := maxX - minX
|
||||
frameH := maxY - minY
|
||||
v.frames = make([]*ebiten.Image, v.framesToAnimate)
|
||||
v.frameLocations = make([]Rectangle, v.framesToAnimate)
|
||||
for frameIndex := range v.frames {
|
||||
v.frames[frameIndex], _ = ebiten.NewImage(int(frameW), int(frameH), ebiten.FilterNearest)
|
||||
priorityBase := (v.direction * animationData.FramesPerDirection * v.cof.NumberOfLayers) + (frameIndex * v.cof.NumberOfLayers)
|
||||
for layerIdx := 0; layerIdx < v.cof.NumberOfLayers; layerIdx++ {
|
||||
comp := v.cof.Priority[priorityBase+layerIdx]
|
||||
if _, found := v.cof.CompositeLayers[comp]; !found {
|
||||
continue
|
||||
}
|
||||
direction := v.dcc.Directions[v.direction]
|
||||
frame := direction.Frames[frameIndex]
|
||||
pixelData := make([]byte, 4*frameW*frameH)
|
||||
for y := 0; y < direction.Box.Height; y++ {
|
||||
for x := 0; x < direction.Box.Width; x++ {
|
||||
paletteIndex := frame.PixelData[x+(y*direction.Box.Width)]
|
||||
|
||||
if paletteIndex == 0 {
|
||||
continue
|
||||
}
|
||||
color := Palettes[v.palette].Colors[paletteIndex]
|
||||
actualX := x + direction.Box.Left - int(minX)
|
||||
actualY := y + direction.Box.Top - int(minY)
|
||||
pixelData[(actualX*4)+(actualY*int(frameW)*4)] = color.R
|
||||
pixelData[(actualX*4)+(actualY*int(frameW)*4)+1] = color.G
|
||||
pixelData[(actualX*4)+(actualY*int(frameW)*4)+2] = color.B
|
||||
pixelData[(actualX*4)+(actualY*int(frameW)*4)+3] = 255
|
||||
}
|
||||
}
|
||||
v.frames[frameIndex].ReplacePixels(pixelData)
|
||||
v.frameLocations[frameIndex] = Rectangle{
|
||||
Left: int(minX),
|
||||
Top: int(minY),
|
||||
Width: int(frameW),
|
||||
Height: int(frameH),
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
244
Common/Cof.go
Normal file
244
Common/Cof.go
Normal file
@ -0,0 +1,244 @@
|
||||
package Common
|
||||
|
||||
import "strings"
|
||||
|
||||
type AnimationMode int
|
||||
|
||||
const (
|
||||
AnimationModePlayerDeath AnimationMode = 0
|
||||
AnimationModePlayerNeutral AnimationMode = 1
|
||||
AnimationModePlayerWalk AnimationMode = 2
|
||||
AnimationModePlayerRun AnimationMode = 3
|
||||
AnimationModePlayerGetHit AnimationMode = 4
|
||||
AnimationModePlayerTownNeutral AnimationMode = 5
|
||||
AnimationModePlayerTownWalk AnimationMode = 6
|
||||
AnimationModePlayerAttack1 AnimationMode = 7
|
||||
AnimationModePlayerAttack2 AnimationMode = 8
|
||||
AnimationModePlayerBlock AnimationMode = 9
|
||||
AnimationModePlayerCast AnimationMode = 10
|
||||
AnimationModePlayerThrow AnimationMode = 11
|
||||
AnimationModePlayerKick AnimationMode = 12
|
||||
AnimationModePlayerSkill1 AnimationMode = 13
|
||||
AnimationModePlayerSkill2 AnimationMode = 14
|
||||
AnimationModePlayerSkill3 AnimationMode = 15
|
||||
AnimationModePlayerSkill4 AnimationMode = 16
|
||||
AnimationModePlayerDead AnimationMode = 17
|
||||
AnimationModePlayerSequence AnimationMode = 18
|
||||
AnimationModePlayerKnockBack AnimationMode = 19
|
||||
AnimationModeMonsterDeath AnimationMode = 20
|
||||
AnimationModeMonsterNeutral AnimationMode = 21
|
||||
AnimationModeMonsterWalk AnimationMode = 22
|
||||
AnimationModeMonsterGetHit AnimationMode = 23
|
||||
AnimationModeMonsterAttack1 AnimationMode = 24
|
||||
AnimationModeMonsterAttack2 AnimationMode = 25
|
||||
AnimationModeMonsterBlock AnimationMode = 26
|
||||
AnimationModeMonsterCast AnimationMode = 27
|
||||
AnimationModeMonsterSkill1 AnimationMode = 28
|
||||
AnimationModeMonsterSkill2 AnimationMode = 29
|
||||
AnimationModeMonsterSkill3 AnimationMode = 30
|
||||
AnimationModeMonsterSkill4 AnimationMode = 31
|
||||
AnimationModeMonsterDead AnimationMode = 32
|
||||
AnimationModeMonsterKnockback AnimationMode = 33
|
||||
AnimationModeMonsterSequence AnimationMode = 34
|
||||
AnimationModeMonsterRun AnimationMode = 35
|
||||
AnimationModeObjectNeutral AnimationMode = 36
|
||||
AnimationModeObjectOperating AnimationMode = 37
|
||||
AnimationModeObjectOpened AnimationMode = 38
|
||||
AnimationModeObjectSpecial1 AnimationMode = 39
|
||||
AnimationModeObjectSpecial2 AnimationMode = 40
|
||||
AnimationModeObjectSpecial3 AnimationMode = 41
|
||||
AnimationModeObjectSpecial4 AnimationMode = 42
|
||||
AnimationModeObjectSpecial5 AnimationMode = 43
|
||||
)
|
||||
|
||||
var AnimationModeStr = map[AnimationMode]string{
|
||||
AnimationModePlayerDeath: "DT",
|
||||
AnimationModePlayerNeutral: "NU",
|
||||
AnimationModePlayerWalk: "WL",
|
||||
AnimationModePlayerRun: "RN",
|
||||
AnimationModePlayerGetHit: "GH",
|
||||
AnimationModePlayerTownNeutral: "TN",
|
||||
AnimationModePlayerTownWalk: "TW",
|
||||
AnimationModePlayerAttack1: "A1",
|
||||
AnimationModePlayerAttack2: "A2",
|
||||
AnimationModePlayerBlock: "BL",
|
||||
AnimationModePlayerCast: "SC",
|
||||
AnimationModePlayerThrow: "TH",
|
||||
AnimationModePlayerKick: "KK",
|
||||
AnimationModePlayerSkill1: "S1",
|
||||
AnimationModePlayerSkill2: "S2",
|
||||
AnimationModePlayerSkill3: "S3",
|
||||
AnimationModePlayerSkill4: "S4",
|
||||
AnimationModePlayerDead: "DD",
|
||||
AnimationModePlayerSequence: "GH",
|
||||
AnimationModePlayerKnockBack: "GH",
|
||||
AnimationModeMonsterDeath: "DT",
|
||||
AnimationModeMonsterNeutral: "NU",
|
||||
AnimationModeMonsterWalk: "WL",
|
||||
AnimationModeMonsterGetHit: "GH",
|
||||
AnimationModeMonsterAttack1: "A1",
|
||||
AnimationModeMonsterAttack2: "A2",
|
||||
AnimationModeMonsterBlock: "BL",
|
||||
AnimationModeMonsterCast: "SC",
|
||||
AnimationModeMonsterSkill1: "S1",
|
||||
AnimationModeMonsterSkill2: "S2",
|
||||
AnimationModeMonsterSkill3: "S3",
|
||||
AnimationModeMonsterSkill4: "S4",
|
||||
AnimationModeMonsterDead: "DD",
|
||||
AnimationModeMonsterKnockback: "GH",
|
||||
AnimationModeMonsterSequence: "xx",
|
||||
AnimationModeMonsterRun: "RN",
|
||||
AnimationModeObjectNeutral: "NU",
|
||||
AnimationModeObjectOperating: "OP",
|
||||
AnimationModeObjectOpened: "ON",
|
||||
AnimationModeObjectSpecial1: "S1",
|
||||
AnimationModeObjectSpecial2: "S2",
|
||||
AnimationModeObjectSpecial3: "S3",
|
||||
AnimationModeObjectSpecial4: "S4",
|
||||
AnimationModeObjectSpecial5: "S5",
|
||||
}
|
||||
|
||||
type CompositeType int
|
||||
|
||||
const (
|
||||
CompositeTypeHead CompositeType = 0
|
||||
CompositeTypeTorso CompositeType = 1
|
||||
CompositeTypeLegs CompositeType = 2
|
||||
CompositeTypeRightArm CompositeType = 3
|
||||
CompositeTypeLeftArm CompositeType = 4
|
||||
CompositeTypeRightHand CompositeType = 5
|
||||
CompositeTypeLeftHand CompositeType = 6
|
||||
CompositeTypeShield CompositeType = 7
|
||||
CompositeTypeSpecial1 CompositeType = 8
|
||||
CompositeTypeSpecial2 CompositeType = 9
|
||||
CompositeTypeSpecial3 CompositeType = 10
|
||||
CompositeTypeSpecial4 CompositeType = 11
|
||||
CompositeTypeSpecial5 CompositeType = 12
|
||||
CompositeTypeSpecial6 CompositeType = 13
|
||||
CompositeTypeSpecial7 CompositeType = 14
|
||||
CompositeTypeSpecial8 CompositeType = 15
|
||||
CompositeTypeMax CompositeType = 16
|
||||
)
|
||||
|
||||
type DrawEffect int
|
||||
|
||||
const (
|
||||
DrawEffectPctTransparency75 = 0 //75 % transparency (colormaps 561-816 in a .pl2)
|
||||
DrawEffectPctTransparency50 = 1 //50 % transparency (colormaps 305-560 in a .pl2)
|
||||
DrawEffectPctTransparency25 = 2 //25 % transparency (colormaps 49-304 in a .pl2)
|
||||
DrawEffectScreen = 3 //Screen (colormaps 817-1072 in a .pl2)
|
||||
DrawEffectLuminance = 4 //luminance (colormaps 1073-1328 in a .pl2)
|
||||
DrawEffectBringAlphaBlending = 5 //bright alpha blending (colormaps 1457-1712 in a .pl2)
|
||||
)
|
||||
|
||||
type WeaponClass int
|
||||
|
||||
const (
|
||||
WeaponClassNone WeaponClass = 0
|
||||
WeaponClassHandToHand WeaponClass = 1
|
||||
WeaponClassBow WeaponClass = 2
|
||||
WeaponClassOneHandSwing WeaponClass = 3
|
||||
WeaponClassOneHandThrust WeaponClass = 4
|
||||
WeaponClassStaff WeaponClass = 5
|
||||
WeaponClassTwoHandSwing WeaponClass = 6
|
||||
WeaponClassTwoHandThrust WeaponClass = 7
|
||||
WeaponClassCrossbow WeaponClass = 8
|
||||
WeaponClassLeftJabRightSwing WeaponClass = 9
|
||||
WeaponClassLeftJabRightThrust WeaponClass = 10
|
||||
WeaponClassLeftSwingRightSwing WeaponClass = 11
|
||||
WeaponClassLeftSwingRightThrust WeaponClass = 12
|
||||
WeaponClassOneHandToHand WeaponClass = 13
|
||||
WeaponClassTwoHandToHand WeaponClass = 14
|
||||
)
|
||||
|
||||
var WeaponClassStr = map[WeaponClass]string{
|
||||
WeaponClassNone: "",
|
||||
WeaponClassHandToHand: "hth",
|
||||
WeaponClassBow: "bow",
|
||||
WeaponClassOneHandSwing: "1hs",
|
||||
WeaponClassOneHandThrust: "1ht",
|
||||
WeaponClassStaff: "stf",
|
||||
WeaponClassTwoHandSwing: "2hs",
|
||||
WeaponClassTwoHandThrust: "2ht",
|
||||
WeaponClassCrossbow: "xbw",
|
||||
WeaponClassLeftJabRightSwing: "1js",
|
||||
WeaponClassLeftJabRightThrust: "1jt",
|
||||
WeaponClassLeftSwingRightSwing: "1ss",
|
||||
WeaponClassLeftSwingRightThrust: "1st",
|
||||
WeaponClassOneHandToHand: "ht1",
|
||||
WeaponClassTwoHandToHand: "ht2",
|
||||
}
|
||||
|
||||
func GetWeaponClass(val string) WeaponClass {
|
||||
for weaponClass, weaponStr := range WeaponClassStr {
|
||||
if val != weaponStr {
|
||||
continue
|
||||
}
|
||||
return weaponClass
|
||||
}
|
||||
return WeaponClassNone
|
||||
}
|
||||
|
||||
type AnimationFrame int
|
||||
|
||||
const (
|
||||
AnimationFrameNoEvent AnimationFrame = 0
|
||||
AnimationFrameAttack AnimationFrame = 1
|
||||
AnimationFrameMissile AnimationFrame = 2
|
||||
AnimationFrameSound AnimationFrame = 3
|
||||
AnimationFrameSkill AnimationFrame = 4
|
||||
)
|
||||
|
||||
type CofLayer struct {
|
||||
Type CompositeType
|
||||
Shadow byte
|
||||
Transparent bool
|
||||
DrawEffect DrawEffect
|
||||
WeaponClass WeaponClass
|
||||
}
|
||||
|
||||
type Cof struct {
|
||||
NumberOfDirections int
|
||||
FramesPerDirection int
|
||||
NumberOfLayers int
|
||||
CofLayers []*CofLayer
|
||||
CompositeLayers map[CompositeType]int
|
||||
AnimationFrames []AnimationFrame
|
||||
Priority []CompositeType
|
||||
}
|
||||
|
||||
func LoadCof(fileName string, fileProvider FileProvider) *Cof {
|
||||
result := &Cof{}
|
||||
fileData := fileProvider.LoadFile(fileName)
|
||||
streamReader := CreateStreamReader(fileData)
|
||||
result.NumberOfLayers = int(streamReader.GetByte())
|
||||
result.FramesPerDirection = int(streamReader.GetByte())
|
||||
result.NumberOfDirections = int(streamReader.GetByte())
|
||||
streamReader.SkipBytes(25) // Skip 25 unknown bytes...
|
||||
result.CofLayers = make([]*CofLayer, 0)
|
||||
result.CompositeLayers = make(map[CompositeType]int, 0)
|
||||
for i := 0; i < result.NumberOfLayers; i++ {
|
||||
layer := &CofLayer{}
|
||||
layer.Type = CompositeType(streamReader.GetByte())
|
||||
layer.Shadow = streamReader.GetByte()
|
||||
streamReader.SkipBytes(1) // Unknown
|
||||
layer.Transparent = streamReader.GetByte() != 0
|
||||
layer.DrawEffect = DrawEffect(streamReader.GetByte())
|
||||
weaponClassStr, _ := streamReader.ReadBytes(4)
|
||||
layer.WeaponClass = GetWeaponClass(strings.TrimSpace(strings.ReplaceAll(string(weaponClassStr), string(0), "")))
|
||||
result.CofLayers = append(result.CofLayers, layer)
|
||||
result.CompositeLayers[layer.Type] = i
|
||||
}
|
||||
animationFrameBytes, _ := streamReader.ReadBytes(result.FramesPerDirection)
|
||||
result.AnimationFrames = make([]AnimationFrame, result.FramesPerDirection)
|
||||
for i := range animationFrameBytes {
|
||||
result.AnimationFrames[i] = AnimationFrame(animationFrameBytes[i])
|
||||
}
|
||||
priorityLen := result.FramesPerDirection * result.NumberOfDirections * result.NumberOfLayers
|
||||
result.Priority = make([]CompositeType, priorityLen)
|
||||
priorityBytes, _ := streamReader.ReadBytes(priorityLen)
|
||||
for i := range priorityBytes {
|
||||
result.Priority[i] = CompositeType(priorityBytes[i])
|
||||
}
|
||||
return result
|
||||
}
|
@ -513,5 +513,6 @@ func LoadDCC(path string, fileProvider FileProvider) *DCC {
|
||||
for i := 0; i < result.NumberOfDirections; i++ {
|
||||
result.Directions[i] = CreateDCCDirection(CreateBitMuncher(fileData, directionOffsets[i]*8), result)
|
||||
}
|
||||
|
||||
return result
|
||||
}
|
||||
|
@ -58,3 +58,9 @@ func IsoToScreen(isoX, isoY, modX, modY int) (int, int) {
|
||||
screenY := (isoX + isoY) * 40
|
||||
return screenX + modX, screenY + modY
|
||||
}
|
||||
|
||||
func ScreenToIso(sx, sy float64) (float64, float64) {
|
||||
x := (sx/80 + sy/40) / 2
|
||||
y := (sy/40 - (sx / 80)) / 2
|
||||
return x, y
|
||||
}
|
||||
|
@ -2,7 +2,6 @@ package Common
|
||||
|
||||
import (
|
||||
"log"
|
||||
"strings"
|
||||
|
||||
"github.com/OpenDiablo2/OpenDiablo2/PaletteDefs"
|
||||
)
|
||||
@ -34,15 +33,15 @@ func CreatePalette(name PaletteDefs.PaletteType, data []byte) PaletteRec {
|
||||
return result
|
||||
}
|
||||
|
||||
func LoadPalettes(mpqFiles map[string]*MpqFileRecord, fileProvider FileProvider) {
|
||||
func LoadPalettes(mpqFiles map[string]string, fileProvider FileProvider) {
|
||||
Palettes = make(map[PaletteDefs.PaletteType]PaletteRec)
|
||||
for file := range mpqFiles {
|
||||
if strings.Index(file, "/data/global/palette/") != 0 || strings.Index(file, ".dat") != len(file)-4 {
|
||||
continue
|
||||
}
|
||||
nameParts := strings.Split(file, `/`)
|
||||
paletteName := PaletteDefs.PaletteType(nameParts[len(nameParts)-2])
|
||||
palette := CreatePalette(paletteName, fileProvider.LoadFile(file))
|
||||
for _, pal := range []string{
|
||||
"act1", "act2", "act3", "act4", "act5", "endgame", "endgame2", "fechar", "loading",
|
||||
"menu0", "menu1", "menu2", "menu3", "menu4", "sky", "static", "trademark", "units",
|
||||
} {
|
||||
filePath := `data\global\palette\` + pal + `\pal.dat`
|
||||
paletteName := PaletteDefs.PaletteType(pal)
|
||||
palette := CreatePalette(paletteName, fileProvider.LoadFile(filePath))
|
||||
Palettes[paletteName] = palette
|
||||
}
|
||||
log.Printf("Loaded %d palettes", len(Palettes))
|
||||
|
@ -14,3 +14,7 @@ func (v *Rectangle) Bottom() int {
|
||||
func (v *Rectangle) Right() int {
|
||||
return v.Left + v.Width
|
||||
}
|
||||
|
||||
func (v *Rectangle) IsInRect(x, y int) bool {
|
||||
return x >= v.Left && x < v.Left+v.Width && y >= v.Top && y < v.Top+v.Height
|
||||
}
|
||||
|
@ -2,7 +2,6 @@ package Core
|
||||
|
||||
import (
|
||||
"encoding/json"
|
||||
"fmt"
|
||||
"io/ioutil"
|
||||
"log"
|
||||
"math"
|
||||
@ -11,12 +10,13 @@ import (
|
||||
"strings"
|
||||
"sync"
|
||||
|
||||
"github.com/OpenDiablo2/OpenDiablo2/MPQ"
|
||||
|
||||
"github.com/OpenDiablo2/OpenDiablo2/PaletteDefs"
|
||||
|
||||
"github.com/OpenDiablo2/OpenDiablo2/Sound"
|
||||
|
||||
"github.com/OpenDiablo2/OpenDiablo2/Common"
|
||||
"github.com/OpenDiablo2/OpenDiablo2/MPQ"
|
||||
"github.com/OpenDiablo2/OpenDiablo2/ResourcePaths"
|
||||
"github.com/OpenDiablo2/OpenDiablo2/Scenes"
|
||||
"github.com/OpenDiablo2/OpenDiablo2/UI"
|
||||
@ -42,17 +42,17 @@ type EngineConfig struct {
|
||||
|
||||
// Engine is the core OpenDiablo2 engine
|
||||
type Engine struct {
|
||||
Settings *EngineConfig // Engine configuration settings from json file
|
||||
Files map[string]*Common.MpqFileRecord // Map that defines which files are in which MPQs
|
||||
CheckedPatch map[string]bool // First time we check a file, we'll check if it's in the patch. This notes that we've already checked that.
|
||||
LoadingSprite *Common.Sprite // The sprite shown when loading stuff
|
||||
loadingProgress float64 // LoadingProcess is a range between 0.0 and 1.0. If set, loading screen displays.
|
||||
stepLoadingSize float64 // The size for each loading step
|
||||
CurrentScene Scenes.Scene // The current scene being rendered
|
||||
UIManager *UI.Manager // The UI manager
|
||||
SoundManager *Sound.Manager // The sound manager
|
||||
nextScene Scenes.Scene // The next scene to be loaded at the end of the game loop
|
||||
fullscreenKey bool // When true, the fullscreen toggle is still being pressed
|
||||
Settings *EngineConfig // Engine configuration settings from json file
|
||||
Files map[string]string // Map that defines which files are in which MPQs
|
||||
CheckedPatch map[string]bool // First time we check a file, we'll check if it's in the patch. This notes that we've already checked that.
|
||||
LoadingSprite *Common.Sprite // The sprite shown when loading stuff
|
||||
loadingProgress float64 // LoadingProcess is a range between 0.0 and 1.0. If set, loading screen displays.
|
||||
stepLoadingSize float64 // The size for each loading step
|
||||
CurrentScene Scenes.Scene // The current scene being rendered
|
||||
UIManager *UI.Manager // The UI manager
|
||||
SoundManager *Sound.Manager // The sound manager
|
||||
nextScene Scenes.Scene // The next scene to be loaded at the end of the game loop
|
||||
fullscreenKey bool // When true, the fullscreen toggle is still being pressed
|
||||
}
|
||||
|
||||
// CreateEngine creates and instance of the OpenDiablo2 engine
|
||||
@ -115,6 +115,11 @@ func (v *Engine) loadConfigurationFile() {
|
||||
}
|
||||
}
|
||||
|
||||
func (v *Engine) mapMpqFiles() {
|
||||
v.Files = make(map[string]string)
|
||||
}
|
||||
|
||||
/*
|
||||
func (v *Engine) mapMpqFiles() {
|
||||
log.Println("mapping mpq file structure")
|
||||
v.Files = make(map[string]*Common.MpqFileRecord)
|
||||
@ -229,6 +234,37 @@ func (v *Engine) LoadFile(fileName string) []byte {
|
||||
mutex.Unlock()
|
||||
return result
|
||||
}
|
||||
*/
|
||||
var mutex sync.Mutex
|
||||
|
||||
func (v *Engine) LoadFile(fileName string) []byte {
|
||||
fileName = strings.ReplaceAll(fileName, "{LANG}", ResourcePaths.LanguageCode)
|
||||
fileName = strings.ToLower(fileName)
|
||||
fileName = strings.ReplaceAll(fileName, `/`, "\\")
|
||||
if fileName[0] == '\\' {
|
||||
fileName = fileName[1:]
|
||||
}
|
||||
mutex.Lock()
|
||||
defer mutex.Unlock()
|
||||
// TODO: May want to cache some things if performance becomes an issue
|
||||
cachedMpqFile, cacheExists := v.Files[fileName]
|
||||
if cacheExists {
|
||||
mpq, _ := MPQ.Load(cachedMpqFile)
|
||||
result, _ := mpq.ReadFile(fileName)
|
||||
return result
|
||||
}
|
||||
for _, mpqFile := range v.Settings.MpqLoadOrder {
|
||||
mpq, _ := MPQ.Load(path.Join(v.Settings.MpqPath, mpqFile))
|
||||
if !mpq.FileExists(fileName) {
|
||||
continue
|
||||
}
|
||||
v.Files[fileName] = path.Join(v.Settings.MpqPath, mpqFile)
|
||||
result, _ := mpq.ReadFile(fileName)
|
||||
return result
|
||||
}
|
||||
log.Fatalf("Could not load %s from MPQs", fileName)
|
||||
return []byte{}
|
||||
}
|
||||
|
||||
// IsLoading returns true if the engine is currently in a loading state
|
||||
func (v *Engine) IsLoading() bool {
|
||||
|
@ -242,7 +242,6 @@ func (v *MPQ) Close() {
|
||||
}
|
||||
|
||||
func (v MPQ) FileExists(fileName string) bool {
|
||||
fileName = strings.ReplaceAll(fileName, "{LANG}", ResourcePaths.LanguageCode)
|
||||
_, err := v.getFileHashEntry(fileName)
|
||||
return err == nil
|
||||
}
|
||||
|
140
Map/Engine.go
140
Map/Engine.go
@ -1,7 +1,7 @@
|
||||
package Map
|
||||
|
||||
import (
|
||||
"image"
|
||||
"math"
|
||||
"math/rand"
|
||||
|
||||
"github.com/OpenDiablo2/OpenDiablo2/Common"
|
||||
@ -10,7 +10,7 @@ import (
|
||||
)
|
||||
|
||||
type EngineRegion struct {
|
||||
Rect image.Rectangle
|
||||
Rect Common.Rectangle
|
||||
Region *Region
|
||||
}
|
||||
|
||||
@ -37,76 +37,116 @@ func (v *Engine) GenerateMap(regionType RegionIdType, levelPreset int) {
|
||||
randomSource := rand.NewSource(v.gameState.Seed)
|
||||
region := LoadRegion(randomSource, regionType, levelPreset, v.fileProvider)
|
||||
v.regions = append(v.regions, EngineRegion{
|
||||
Rect: image.Rectangle{image.Point{0, 0}, image.Point{int(region.TileWidth), int(region.TileHeight)}},
|
||||
Rect: Common.Rectangle{0, 0, int(region.TileWidth), int(region.TileHeight)},
|
||||
Region: region,
|
||||
})
|
||||
v.soundManager.PlayBGM("/data/global/music/Act1/tristram.wav") // TODO: Temp stuff here
|
||||
v.soundManager.PlayBGM("/data/global/music/Act1/town1.wav") // TODO: Temp stuff here
|
||||
}
|
||||
|
||||
func (v *Engine) GetRegionAt(x, y int) *Region {
|
||||
if v.regions == nil {
|
||||
return nil
|
||||
}
|
||||
for _, region := range v.regions {
|
||||
if !region.Rect.IsInRect(x, y) {
|
||||
continue
|
||||
}
|
||||
return region.Region
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
func (v *Engine) Render(target *ebiten.Image) {
|
||||
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++ {
|
||||
sx, sy := Common.IsoToScreen(x, y, int(v.OffsetX), int(v.OffsetY))
|
||||
if sx > -160 && sy > -160 && sx <= 800 && sy <= 1000 {
|
||||
tile := v.regions[0].Region.DS1.Tiles[y][x]
|
||||
for i := range tile.Floors {
|
||||
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)
|
||||
for _, region := range v.regions {
|
||||
for y := 0; y < int(region.Region.TileHeight); y++ {
|
||||
offX := -(y * 80)
|
||||
offY := y * 40
|
||||
for x := 0; x < int(region.Region.TileWidth); x++ {
|
||||
sx, sy := Common.IsoToScreen(x, y, int(v.OffsetX), int(v.OffsetY))
|
||||
if sx > -160 && sy > -160 && sx <= 880 && sy <= 1000 {
|
||||
tile := region.Region.DS1.Tiles[y][x]
|
||||
for i := range tile.Floors {
|
||||
if tile.Floors[i].Hidden || tile.Floors[i].Prop1 == 0 {
|
||||
continue
|
||||
}
|
||||
region.Region.RenderTile(offX+int(v.OffsetX), offY+int(v.OffsetY), x, y, RegionLayerTypeFloors, i, target)
|
||||
}
|
||||
}
|
||||
offX += 80
|
||||
offY += 40
|
||||
}
|
||||
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++ {
|
||||
sx, sy := Common.IsoToScreen(x, y, int(v.OffsetX), int(v.OffsetY))
|
||||
if sx > -160 && sy > -160 && sx <= 800 && sy <= 1000 {
|
||||
tile := v.regions[0].Region.DS1.Tiles[y][x]
|
||||
for i := range tile.Shadows {
|
||||
if tile.Shadows[i].Hidden || tile.Shadows[i].Prop1 == 0 {
|
||||
for _, region := range v.regions {
|
||||
for y := 0; y < int(region.Region.TileHeight); y++ {
|
||||
offX := -(y * 80)
|
||||
offY := y * 40
|
||||
for x := 0; x < int(region.Region.TileWidth); x++ {
|
||||
sx, sy := Common.IsoToScreen(x, y, int(v.OffsetX), int(v.OffsetY))
|
||||
if sx > -160 && sy > -160 && sx <= 880 && sy <= 1000 {
|
||||
tile := region.Region.DS1.Tiles[y][x]
|
||||
for i := range tile.Shadows {
|
||||
if tile.Shadows[i].Hidden || tile.Shadows[i].Prop1 == 0 {
|
||||
continue
|
||||
}
|
||||
region.Region.RenderTile(offX+int(v.OffsetX), offY+int(v.OffsetY), x, y, RegionLayerTypeShadows, i, target)
|
||||
}
|
||||
}
|
||||
offX += 80
|
||||
offY += 40
|
||||
}
|
||||
}
|
||||
}
|
||||
for _, region := range v.regions {
|
||||
for y := 0; y < int(region.Region.TileHeight); y++ {
|
||||
offX := -(y * 80)
|
||||
offY := y * 40
|
||||
for x := 0; x < int(region.Region.TileWidth); x++ {
|
||||
tile := region.Region.DS1.Tiles[y][x]
|
||||
for i := range tile.Walls {
|
||||
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, RegionLayerTypeShadows, i, target)
|
||||
region.Region.RenderTile(offX+int(v.OffsetX), offY+int(v.OffsetY), x, y, RegionLayerTypeWalls, i, target)
|
||||
}
|
||||
offX += 80
|
||||
offY += 40
|
||||
}
|
||||
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 || tile.Walls[i].Orientation == 10 || tile.Walls[i].Orientation == 11 || tile.Walls[i].Orientation == 0 {
|
||||
continue
|
||||
for _, region := range v.regions {
|
||||
for y := 0; y < int(region.Region.TileHeight); y++ {
|
||||
offX := -(y * 80)
|
||||
offY := y * 40
|
||||
for x := 0; x < int(region.Region.TileWidth); x++ {
|
||||
tile := region.Region.DS1.Tiles[y][x]
|
||||
for i := range tile.Walls {
|
||||
if tile.Walls[i].Hidden || tile.Walls[i].Orientation != 15 {
|
||||
continue
|
||||
}
|
||||
region.Region.RenderTile(offX+int(v.OffsetX), offY+int(v.OffsetY), x, y, RegionLayerTypeWalls, i, target)
|
||||
}
|
||||
v.regions[0].Region.RenderTile(offX+int(v.OffsetX), offY+int(v.OffsetY), x, y, RegionLayerTypeWalls, i, target)
|
||||
offX += 80
|
||||
offY += 40
|
||||
}
|
||||
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
|
||||
for _, region := range v.regions {
|
||||
for y := 0; y < int(region.Region.TileHeight); y++ {
|
||||
offX := -(y * 80)
|
||||
offY := y * 40
|
||||
for x := 0; x < int(region.Region.TileWidth); x++ {
|
||||
sx, sy := Common.IsoToScreen(x, y, int(v.OffsetX), int(v.OffsetY))
|
||||
if sx > -160 && sy > -160 && sx <= 880 && sy <= 1000 {
|
||||
for _, obj := range region.Region.AnimationEntities {
|
||||
if int(math.Floor(obj.LocationX)) == x && int(math.Floor(obj.LocationY)) == y {
|
||||
obj.Render(target, offX+int(v.OffsetX), offY+int(v.OffsetY))
|
||||
}
|
||||
}
|
||||
}
|
||||
v.regions[0].Region.RenderTile(offX+int(v.OffsetX), offY+int(v.OffsetY), x, y, RegionLayerTypeWalls, i, target)
|
||||
offX += 80
|
||||
offY += 40
|
||||
}
|
||||
offX += 80
|
||||
offY += 40
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -6,7 +6,7 @@ import (
|
||||
"math"
|
||||
"math/rand"
|
||||
"strconv"
|
||||
"strings"
|
||||
"sync"
|
||||
|
||||
"github.com/OpenDiablo2/OpenDiablo2/PaletteDefs"
|
||||
|
||||
@ -22,16 +22,17 @@ type TileCacheRecord struct {
|
||||
}
|
||||
|
||||
type Region struct {
|
||||
levelType Common.LevelTypeRecord
|
||||
levelPreset *Common.LevelPresetRecord
|
||||
TileWidth int32
|
||||
TileHeight int32
|
||||
Tiles []Tile
|
||||
DS1 *DS1
|
||||
Palette Common.PaletteRec
|
||||
FloorCache map[uint32]*TileCacheRecord
|
||||
ShadowCache map[uint32]*TileCacheRecord
|
||||
WallCache map[uint32]*TileCacheRecord
|
||||
LevelType Common.LevelTypeRecord
|
||||
levelPreset *Common.LevelPresetRecord
|
||||
TileWidth int32
|
||||
TileHeight int32
|
||||
Tiles []Tile
|
||||
DS1 *DS1
|
||||
Palette Common.PaletteRec
|
||||
FloorCache map[uint32]*TileCacheRecord
|
||||
ShadowCache map[uint32]*TileCacheRecord
|
||||
WallCache map[uint32]*TileCacheRecord
|
||||
AnimationEntities []*Common.AnimatedEntity
|
||||
}
|
||||
|
||||
type RegionLayerType int
|
||||
@ -84,16 +85,16 @@ const (
|
||||
|
||||
func LoadRegion(seed rand.Source, levelType RegionIdType, levelPreset int, fileProvider Common.FileProvider) *Region {
|
||||
result := &Region{
|
||||
levelType: Common.LevelTypes[levelType],
|
||||
LevelType: Common.LevelTypes[levelType],
|
||||
levelPreset: Common.LevelPresets[levelPreset],
|
||||
Tiles: make([]Tile, 0),
|
||||
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)))]
|
||||
result.Palette = Common.Palettes[PaletteDefs.PaletteType("act"+strconv.Itoa(int(result.LevelType.Act)))]
|
||||
//\bm := result.levelPreset.Dt1Mask
|
||||
for _, levelTypeDt1 := range result.levelType.Files {
|
||||
for _, levelTypeDt1 := range result.LevelType.Files {
|
||||
/*
|
||||
if bm&1 == 0 {
|
||||
bm >>= 1
|
||||
@ -120,22 +121,32 @@ func LoadRegion(seed rand.Source, levelType RegionIdType, levelPreset int, fileP
|
||||
result.DS1 = LoadDS1("/data/global/tiles/"+levelFile, fileProvider)
|
||||
result.TileWidth = result.DS1.Width
|
||||
result.TileHeight = result.DS1.Height
|
||||
var wg sync.WaitGroup
|
||||
wg.Add(len(result.DS1.Objects))
|
||||
result.AnimationEntities = make([]*Common.AnimatedEntity, 0)
|
||||
for _, object := range result.DS1.Objects {
|
||||
switch object.Lookup.Type {
|
||||
case Common.ObjectTypeCharacter:
|
||||
case Common.ObjectTypeItem:
|
||||
if object.Lookup.Base == "" {
|
||||
continue
|
||||
go func(object Object) {
|
||||
defer wg.Done()
|
||||
switch object.Lookup.Type {
|
||||
case Common.ObjectTypeCharacter:
|
||||
case Common.ObjectTypeItem:
|
||||
if object.Lookup.Base == "" || object.Lookup.Token == "" || object.Lookup.TR == "" {
|
||||
return
|
||||
}
|
||||
animEntity := Common.CreateAnimatedEntity(object.Lookup.Base, object.Lookup.Token, object.Lookup.TR, PaletteDefs.Units)
|
||||
animEntity.SetMode(object.Lookup.Mode, object.Lookup.Class, 0, fileProvider)
|
||||
animEntity.LocationX = math.Floor(float64(object.X) / 5)
|
||||
animEntity.LocationY = math.Floor(float64(object.Y) / 5)
|
||||
result.AnimationEntities = append(result.AnimationEntities, animEntity)
|
||||
}
|
||||
objPath := strings.ToLower(object.Lookup.Base + "/" + object.Lookup.Token + "/tr/" + object.Lookup.Token + "tr" + object.Lookup.TR +
|
||||
object.Lookup.Mode + object.Lookup.Class + ".dcc")
|
||||
_ = Common.LoadDCC(objPath, fileProvider) // This is where the magic will happen
|
||||
}
|
||||
}(object)
|
||||
}
|
||||
wg.Wait()
|
||||
return result
|
||||
}
|
||||
|
||||
func (v *Region) RenderTile(offsetX, offsetY, tileX, tileY int, layerType RegionLayerType, layerIndex int, target *ebiten.Image) {
|
||||
offsetX -= 80
|
||||
switch layerType {
|
||||
case RegionLayerTypeFloors:
|
||||
v.renderFloor(v.DS1.Tiles[tileY][tileX].Floors[layerIndex], offsetX, offsetY, target)
|
||||
|
@ -1,11 +1,15 @@
|
||||
package Scenes
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
"math"
|
||||
|
||||
"github.com/OpenDiablo2/OpenDiablo2/Common"
|
||||
"github.com/OpenDiablo2/OpenDiablo2/Map"
|
||||
"github.com/OpenDiablo2/OpenDiablo2/Sound"
|
||||
"github.com/OpenDiablo2/OpenDiablo2/UI"
|
||||
"github.com/hajimehoshi/ebiten"
|
||||
"github.com/hajimehoshi/ebiten/ebitenutil"
|
||||
)
|
||||
|
||||
type MapEngineTest struct {
|
||||
@ -43,16 +47,16 @@ func (v *MapEngineTest) Load() []func() {
|
||||
v.mapEngine.GenerateMap(Map.RegionAct1Town, 1)
|
||||
//v.mapEngine.GenerateMap(Map.RegionAct1Tristram, 300)
|
||||
//v.mapEngine.GenerateMap(Map.RegionAct1Cathedral, 257)
|
||||
//v.mapEngine.GenerateMap(Map.RegionAct2Town, 301) // Broken rendering
|
||||
//v.mapEngine.GenerateMap(Map.RegionAct2Harem, 353)
|
||||
//v.mapEngine.GenerateMap(Map.RegionAct2Town, 301)
|
||||
//v.mapEngine.GenerateMap(Map.RegionAct2Harem, 353) // Crashes on dcc load
|
||||
//v.mapEngine.GenerateMap(Map.RegionAct3Town, 529)
|
||||
//v.mapEngine.GenerateMap(Map.RegionAct3Jungle, 574)
|
||||
//v.mapEngine.GenerateMap(Map.RegionAct4Town, 797)
|
||||
//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.RegionAct5Barricade, 880)
|
||||
//v.mapEngine.GenerateMap(Map.RegionAct4Town, 797) // Broken height of large objects
|
||||
//v.mapEngine.GenerateMap(Map.RegonAct5Town, 863) // Completely broken!!
|
||||
//v.mapEngine.GenerateMap(Map.RegionAct5IceCaves, 1038) // Completely broken!
|
||||
//v.mapEngine.GenerateMap(Map.RegionAct5Siege, 879) // Completely broken!
|
||||
//v.mapEngine.GenerateMap(Map.RegionAct5Lava, 1057) // Broken
|
||||
//v.mapEngine.GenerateMap(Map.RegionAct5Barricade, 880) // Broken
|
||||
|
||||
},
|
||||
}
|
||||
@ -64,6 +68,18 @@ func (v *MapEngineTest) Unload() {
|
||||
|
||||
func (v *MapEngineTest) Render(screen *ebiten.Image) {
|
||||
v.mapEngine.Render(screen)
|
||||
actualX := float64(v.uiManager.CursorX) - v.mapEngine.OffsetX
|
||||
actualY := float64(v.uiManager.CursorY) - v.mapEngine.OffsetY
|
||||
tileX, tileY := Common.ScreenToIso(actualX, actualY)
|
||||
subtileX := int(math.Ceil(math.Mod((tileX*10), 10))) / 2
|
||||
subtileY := int(math.Ceil(math.Mod((tileY*10), 10))) / 2
|
||||
line := fmt.Sprintf("%d, %d (Tile %d.%d, %d.%d)", int(math.Ceil(actualX)), int(math.Ceil(actualY)), int(math.Ceil(tileX)), subtileX, int(math.Ceil(tileY)), subtileY)
|
||||
ebitenutil.DebugPrintAt(screen, line, 5, 5)
|
||||
curRegion := v.mapEngine.GetRegionAt(int(tileX), int(tileY))
|
||||
if curRegion == nil {
|
||||
return
|
||||
}
|
||||
ebitenutil.DebugPrintAt(screen, "Map: "+curRegion.LevelType.Name, 5, 17)
|
||||
}
|
||||
|
||||
func (v *MapEngineTest) Update(tickTime float64) {
|
||||
|
7
go.mod
7
go.mod
@ -5,6 +5,11 @@ go 1.13
|
||||
require (
|
||||
github.com/JoshVarga/blast v0.0.0-20180421040937-681c804fb9f0
|
||||
github.com/giorgisio/goav v0.1.0
|
||||
github.com/hajimehoshi/ebiten v1.9.3
|
||||
github.com/gopherjs/gopherjs v0.0.0-20191106031601-ce3c9ade29de // indirect
|
||||
github.com/gopherjs/gopherwasm v1.1.0 // indirect
|
||||
github.com/hajimehoshi/ebiten v1.10.0
|
||||
github.com/mitchellh/go-homedir v1.1.0
|
||||
golang.org/x/exp v0.0.0-20191030013958-a1ab85dbe136 // indirect
|
||||
golang.org/x/mobile v0.0.0-20191031020345-0945064e013a // indirect
|
||||
golang.org/x/sys v0.0.0-20191105231009-c1f44814a5cd // indirect
|
||||
)
|
||||
|
50
go.sum
50
go.sum
@ -1,14 +1,20 @@
|
||||
dmitri.shuralyov.com/gpu/mtl v0.0.0-20190408044501-666a987793e9/go.mod h1:H6x//7gZCb22OMCxBHrMx7a5I7Hp++hsVxbQ4BYO7hU=
|
||||
github.com/BurntSushi/xgb v0.0.0-20160522181843-27f122750802/go.mod h1:IVnqGOEym/WlBOVXweHU+Q+/VP0lqqI8lqeDx9IjBqo=
|
||||
github.com/JoshVarga/blast v0.0.0-20180421040937-681c804fb9f0 h1:tDnuU0igiBiQFjsvq1Bi7DpoUjqI76VVvW045vpeFeM=
|
||||
github.com/JoshVarga/blast v0.0.0-20180421040937-681c804fb9f0/go.mod h1:h/5OEGj4G+fpYxluLjSMZbFY011ZxAntO98nCl8mrCs=
|
||||
github.com/giorgisio/goav v0.1.0 h1:ZyfG3NfX7PMSimv4ulhmnQJf/XeHpMdGCn+afRmY5Oc=
|
||||
github.com/giorgisio/goav v0.1.0/go.mod h1:RtH8HyxLRLU1iY0pjfhWBKRhnbsnmfoI+FxMwb5bfEo=
|
||||
github.com/go-gl/glfw v0.0.0-20181213070059-819e8ce5125f h1:7MsFMbSn8Lcw0blK4+NEOf8DuHoOBDhJsHz04yh13pM=
|
||||
github.com/go-gl/glfw v0.0.0-20181213070059-819e8ce5125f/go.mod h1:vR7hzQXu2zJy9AVAgeJqvqgH9Q5CA+iKCZ2gyEVpxRU=
|
||||
github.com/go-gl/glfw v0.0.0-20190409004039-e6da0acd62b1 h1:QbL/5oDUmRBzO9/Z7Seo6zf912W/a6Sr4Eu0G/3Jho0=
|
||||
github.com/go-gl/glfw v0.0.0-20190409004039-e6da0acd62b1/go.mod h1:vR7hzQXu2zJy9AVAgeJqvqgH9Q5CA+iKCZ2gyEVpxRU=
|
||||
github.com/gofrs/flock v0.7.0/go.mod h1:F1TvTiK9OcQqauNUHlbJvyl9Qa1QvF/gOUDKA14jxHU=
|
||||
github.com/gofrs/flock v0.7.1/go.mod h1:F1TvTiK9OcQqauNUHlbJvyl9Qa1QvF/gOUDKA14jxHU=
|
||||
github.com/golang/freetype v0.0.0-20170609003504-e2365dfdc4a0/go.mod h1:E/TSTwGwJL78qG/PmXZO1EjYhfJinVAhrmmHX6Z8B9k=
|
||||
github.com/gopherjs/gopherjs v0.0.0-20180628210949-0892b62f0d9f/go.mod h1:wJfORRmW1u3UXTncJ5qlYoELFm8eSnnEO6hX4iZ3EWY=
|
||||
github.com/gopherjs/gopherjs v0.0.0-20180825215210-0210a2f0f73c h1:16eHWuMGvCjSfgRJKqIzapE78onvvTbdi1rMkU00lZw=
|
||||
github.com/gopherjs/gopherjs v0.0.0-20180825215210-0210a2f0f73c/go.mod h1:wJfORRmW1u3UXTncJ5qlYoELFm8eSnnEO6hX4iZ3EWY=
|
||||
github.com/gopherjs/gopherjs v0.0.0-20191106031601-ce3c9ade29de/go.mod h1:wJfORRmW1u3UXTncJ5qlYoELFm8eSnnEO6hX4iZ3EWY=
|
||||
github.com/gopherjs/gopherwasm v0.1.1/go.mod h1:kx4n9a+MzHH0BJJhvlsQ65hqLFXDO/m256AsaDPQ+/4=
|
||||
github.com/gopherjs/gopherwasm v1.0.0/go.mod h1:SkZ8z7CWBz5VXbhJel8TxCmAcsQqzgWGR/8nMhyhZSI=
|
||||
github.com/gopherjs/gopherwasm v1.1.0 h1:fA2uLoctU5+T3OhOn2vYP0DVT6pxc7xhTlBB1paATqQ=
|
||||
@ -16,12 +22,19 @@ github.com/gopherjs/gopherwasm v1.1.0/go.mod h1:SkZ8z7CWBz5VXbhJel8TxCmAcsQqzgWG
|
||||
github.com/gosuri/uilive v0.0.0-20170323041506-ac356e6e42cd/go.mod h1:qkLSc0A5EXSP6B04TrN4oQoxqFI7A8XvoXSlJi8cwk8=
|
||||
github.com/gosuri/uiprogress v0.0.0-20170224063937-d0567a9d84a1/go.mod h1:C1RTYn4Sc7iEyf6j8ft5dyoZ4212h8G1ol9QQluh5+0=
|
||||
github.com/hajimehoshi/bitmapfont v1.1.1/go.mod h1:Hamfxgney7tDSmVOSDh2AWzoDH70OaC+P24zc02Gum4=
|
||||
github.com/hajimehoshi/bitmapfont v1.2.0/go.mod h1:h9QrPk6Ktb2neObTlAbma6Ini1xgMjbJ3w7ysmD7IOU=
|
||||
github.com/hajimehoshi/ebiten v1.9.3 h1:YijWGMBwH2XA1ZytUQFy33UDHeCSS6d4JZKH1wq38O0=
|
||||
github.com/hajimehoshi/ebiten v1.9.3/go.mod h1:XxiJ4Eltvb1KmcD0i6F81eIB1asJhK47y5DC+FPkyso=
|
||||
github.com/hajimehoshi/ebiten v1.10.0 h1:ADLOUI/7aaTOP7GRlQBHVI1Qtvfdt9M6XQqeULSK7Uo=
|
||||
github.com/hajimehoshi/ebiten v1.10.0/go.mod h1:8BJhIws+Jkol+z7hSGP/WFsaDAPTtRQ+ELBPPQetq2w=
|
||||
github.com/hajimehoshi/go-mp3 v0.2.0/go.mod h1:4i+c5pDNKDrxl1iu9iG90/+fhP37lio6gNhjCx9WBJw=
|
||||
github.com/hajimehoshi/go-mp3 v0.2.1/go.mod h1:Rr+2P46iH6PwTPVgSsEwBkon0CK5DxCAeX/Rp65DCTE=
|
||||
github.com/hajimehoshi/oto v0.1.1/go.mod h1:hUiLWeBQnbDu4pZsAhOnGqMI1ZGibS6e2qhQdfpwz04=
|
||||
github.com/hajimehoshi/oto v0.3.3 h1:Wi7VVtxe9sF2rbDBIJtVXnpFWhRfK57hw0JY7tR2qXM=
|
||||
github.com/hajimehoshi/oto v0.3.3/go.mod h1:e9eTLBB9iZto045HLbzfHJIc+jP3xaKrjZTghvb6fdM=
|
||||
github.com/hajimehoshi/oto v0.3.4/go.mod h1:PgjqsBJff0efqL2nlMJidJgVJywLn6M4y8PI4TfeWfA=
|
||||
github.com/hajimehoshi/oto v0.5.2 h1:5FEPlejAsR2PVRqiW7h2PIwp9UWR+8zxj2And102YU4=
|
||||
github.com/hajimehoshi/oto v0.5.2/go.mod h1:0QXGEkbuJRohbJaxr7ZQSxnju7hEhseiPx2hrh6raOI=
|
||||
github.com/jakecoffman/cp v0.1.0/go.mod h1:a3xPx9N8RyFAACD644t2dj/nK4SuLg1v+jL61m2yVo4=
|
||||
github.com/jfreymuth/oggvorbis v1.0.0/go.mod h1:abe6F9QRjuU9l+2jek3gj46lu40N4qlYxh2grqkLEDM=
|
||||
github.com/jfreymuth/vorbis v1.0.0/go.mod h1:8zy3lUAm9K/rJJk223RKy6vjCZTWC61NA2QD06bfOE0=
|
||||
@ -30,18 +43,55 @@ github.com/kr/pty v1.1.1/go.mod h1:pFQYn66WHrOpPYNljwOMqo10TkYh1fy3cYio2l3bCsQ=
|
||||
github.com/kr/text v0.1.0/go.mod h1:4Jbv+DJW3UT/LiOwJeYQe1efqtUx/iVham/4vfdArNI=
|
||||
github.com/mitchellh/go-homedir v1.1.0 h1:lukF9ziXFxDFPkA1vsr5zpc1XuPDn/wFntq5mG+4E0Y=
|
||||
github.com/mitchellh/go-homedir v1.1.0/go.mod h1:SfyaCUpYCn1Vlf4IUYiD9fPX4A5wJrkLzIz1N1q0pr0=
|
||||
github.com/pkg/browser v0.0.0-20180916011732-0a3d74bf9ce4/go.mod h1:4OwLy04Bl9Ef3GJJCoec+30X3LQs/0/m4HFRt/2LUSA=
|
||||
golang.org/x/crypto v0.0.0-20190308221718-c2843e01d9a2/go.mod h1:djNgcEr1/C05ACkg1iLfiJU5Ep61QUkGW8qpdssI0+w=
|
||||
golang.org/x/crypto v0.0.0-20190510104115-cbcb75029529/go.mod h1:yigFU9vqHzYiE8UmvKecakEJjdnWj3jj499lnFckfCI=
|
||||
golang.org/x/exp v0.0.0-20180710024300-14dda7b62fcd h1:nLIcFw7GiqKXUS7HiChg6OAYWgASB2H97dZKd1GhDSs=
|
||||
golang.org/x/exp v0.0.0-20180710024300-14dda7b62fcd/go.mod h1:CJ0aWSM057203Lf6IL+f9T1iT9GByDxfZKAQTCR3kQA=
|
||||
golang.org/x/exp v0.0.0-20190306152737-a1d7652674e8/go.mod h1:CJ0aWSM057203Lf6IL+f9T1iT9GByDxfZKAQTCR3kQA=
|
||||
golang.org/x/exp v0.0.0-20190731235908-ec7cb31e5a56/go.mod h1:JhuoJpWY28nO4Vef9tZUw9qufEGTyX1+7lmHxV5q5G4=
|
||||
golang.org/x/exp v0.0.0-20191030013958-a1ab85dbe136 h1:A1gGSx58LAGVHUUsOf7IiR0u8Xb6W51gRwfDBhkdcaw=
|
||||
golang.org/x/exp v0.0.0-20191030013958-a1ab85dbe136/go.mod h1:JXzH8nQsPlswgeRAPE3MuO9GYsAcnJvJ4vnMwN/5qkY=
|
||||
golang.org/x/image v0.0.0-20180708004352-c73c2afc3b81/go.mod h1:ux5Hcp/YLpHSI86hEcLt0YII63i6oz57MZXIpbrjZUs=
|
||||
golang.org/x/image v0.0.0-20180926015637-991ec62608f3/go.mod h1:ux5Hcp/YLpHSI86hEcLt0YII63i6oz57MZXIpbrjZUs=
|
||||
golang.org/x/image v0.0.0-20190118043309-183bebdce1b2 h1:FNSSV4jv1PrPsiM2iKGpqLPPgYACqh9Muav7Pollk1k=
|
||||
golang.org/x/image v0.0.0-20190118043309-183bebdce1b2/go.mod h1:ux5Hcp/YLpHSI86hEcLt0YII63i6oz57MZXIpbrjZUs=
|
||||
golang.org/x/image v0.0.0-20190227222117-0694c2d4d067/go.mod h1:kZ7UVZpmo3dzQBMxlp+ypCbDeSB+sBbTgSJuh5dn5js=
|
||||
golang.org/x/image v0.0.0-20190703141733-d6a02ce849c9/go.mod h1:FeLwcggjj3mMvU+oOTbSwawSJRM1uh48EjtB4UJZlP0=
|
||||
golang.org/x/image v0.0.0-20190802002840-cff245a6509b/go.mod h1:FeLwcggjj3mMvU+oOTbSwawSJRM1uh48EjtB4UJZlP0=
|
||||
golang.org/x/image v0.0.0-20191009234506-e7c1f5e7dbb8 h1:hVwzHzIUGRjiF7EcUjqNxk3NCfkPxbDKRdnNE1Rpg0U=
|
||||
golang.org/x/image v0.0.0-20191009234506-e7c1f5e7dbb8/go.mod h1:FeLwcggjj3mMvU+oOTbSwawSJRM1uh48EjtB4UJZlP0=
|
||||
golang.org/x/mobile v0.0.0-20180806140643-507816974b79/go.mod h1:z+o9i4GpDbdi3rU15maQ/Ox0txvL9dWGYEHz965HBQE=
|
||||
golang.org/x/mobile v0.0.0-20190127143845-a42111704963 h1:2HSxAhImj2OpXsNjXSqfnv1xtqeCpDjwPB3o1DnQqKM=
|
||||
golang.org/x/mobile v0.0.0-20190127143845-a42111704963/go.mod h1:z+o9i4GpDbdi3rU15maQ/Ox0txvL9dWGYEHz965HBQE=
|
||||
golang.org/x/mobile v0.0.0-20190312151609-d3739f865fa6/go.mod h1:z+o9i4GpDbdi3rU15maQ/Ox0txvL9dWGYEHz965HBQE=
|
||||
golang.org/x/mobile v0.0.0-20190415191353-3e0bab5405d6/go.mod h1:E/iHnbuqvinMTCcRqshq8CkpyQDoeVncDDYHnLhea+o=
|
||||
golang.org/x/mobile v0.0.0-20190719004257-d2bd2a29d028/go.mod h1:E/iHnbuqvinMTCcRqshq8CkpyQDoeVncDDYHnLhea+o=
|
||||
golang.org/x/mobile v0.0.0-20191025110607-73ccc5ba0426/go.mod h1:p895TfNkDgPEmEQrNiOtIl3j98d/tGU95djDj7NfyjQ=
|
||||
golang.org/x/mobile v0.0.0-20191031020345-0945064e013a h1:CrJ8+QyIm2tcw/zt9Rp/vGFsey+jndL1y5EnFwzgGOg=
|
||||
golang.org/x/mobile v0.0.0-20191031020345-0945064e013a/go.mod h1:p895TfNkDgPEmEQrNiOtIl3j98d/tGU95djDj7NfyjQ=
|
||||
golang.org/x/mod v0.1.0/go.mod h1:0QHyrYULN0/3qlju5TqG8bIK38QM8yzMo5ekMj3DlcY=
|
||||
golang.org/x/net v0.0.0-20190311183353-d8887717615a/go.mod h1:t9HGtf8HONx5eT2rtn7q6eTqICYqUVnKs3thJo3Qplg=
|
||||
golang.org/x/net v0.0.0-20190404232315-eb5bcb51f2a3/go.mod h1:t9HGtf8HONx5eT2rtn7q6eTqICYqUVnKs3thJo3Qplg=
|
||||
golang.org/x/net v0.0.0-20190620200207-3b0461eec859/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s=
|
||||
golang.org/x/sync v0.0.0-20181221193216-37e7f081c4d4/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM=
|
||||
golang.org/x/sync v0.0.0-20190423024810-112230192c58/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM=
|
||||
golang.org/x/sys v0.0.0-20181228144115-9a3f9b0469bb/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY=
|
||||
golang.org/x/sys v0.0.0-20190203050204-7ae0202eb74c h1:YeMXU0KQqExdpG959DFhAhfpY8myIsnfqj8lhNFRzzE=
|
||||
golang.org/x/sys v0.0.0-20190203050204-7ae0202eb74c/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY=
|
||||
golang.org/x/sys v0.0.0-20190215142949-d0b11bdaac8a/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY=
|
||||
golang.org/x/sys v0.0.0-20190312061237-fead79001313/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
|
||||
golang.org/x/sys v0.0.0-20190412213103-97732733099d/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
|
||||
golang.org/x/sys v0.0.0-20190429190828-d89cdac9e872/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
|
||||
golang.org/x/sys v0.0.0-20191026070338-33540a1f6037/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
|
||||
golang.org/x/sys v0.0.0-20191105231009-c1f44814a5cd h1:3x5uuvBgE6oaXJjCOvpCC1IpgJogqQ+PqGGU3ZxAgII=
|
||||
golang.org/x/sys v0.0.0-20191105231009-c1f44814a5cd/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
|
||||
golang.org/x/text v0.3.0/go.mod h1:NqM8EUOU14njkJ3fqMW+pc6Ldnwhi/IjpwHt7yyuwOQ=
|
||||
golang.org/x/tools v0.0.0-20190202235157-7414d4c1f71c/go.mod h1:n7NCudcB/nEzxVGmLbDWY5pfWTLqBcC2KZ6jyYvM4mQ=
|
||||
golang.org/x/tools v0.0.0-20190312151545-0bb0c0a6e846/go.mod h1:LCzVGOaR6xXOjkQ3onu1FJEFr0SW1gC7cKk1uF8kGRs=
|
||||
golang.org/x/tools v0.0.0-20190909214602-067311248421/go.mod h1:b+2E5dAYhXwXZwtnZ6UAqBI28+e2cm9otk0dWdXHAEo=
|
||||
golang.org/x/tools v0.0.0-20191012152004-8de300cfc20a/go.mod h1:b+2E5dAYhXwXZwtnZ6UAqBI28+e2cm9otk0dWdXHAEo=
|
||||
golang.org/x/tools v0.0.0-20191026034945-b2104f82a97d/go.mod h1:b+2E5dAYhXwXZwtnZ6UAqBI28+e2cm9otk0dWdXHAEo=
|
||||
golang.org/x/xerrors v0.0.0-20190717185122-a985d3407aa7/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0=
|
||||
gopkg.in/check.v1 v1.0.0-20180628173108-788fd7840127/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0=
|
||||
gopkg.in/check.v1 v1.0.0-20190902080502-41f04d3bba15/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0=
|
||||
|
Loading…
Reference in New Issue
Block a user