mirror of
https://github.com/OpenDiablo2/OpenDiablo2
synced 2025-02-05 16:17:45 -05:00
Initial in-game ui and keyboard controls (#254)
Move player movement out of `Game`, add arrow key movement. Render bottom panel.
This commit is contained in:
parent
61d63bc902
commit
d033c63e18
@ -1,8 +1,6 @@
|
|||||||
package d2scene
|
package d2scene
|
||||||
|
|
||||||
import (
|
import (
|
||||||
"image/color"
|
|
||||||
|
|
||||||
"github.com/OpenDiablo2/D2Shared/d2common/d2enum"
|
"github.com/OpenDiablo2/D2Shared/d2common/d2enum"
|
||||||
"github.com/OpenDiablo2/D2Shared/d2common/d2interface"
|
"github.com/OpenDiablo2/D2Shared/d2common/d2interface"
|
||||||
"github.com/OpenDiablo2/D2Shared/d2common/d2resource"
|
"github.com/OpenDiablo2/D2Shared/d2common/d2resource"
|
||||||
@ -11,10 +9,12 @@ import (
|
|||||||
"github.com/OpenDiablo2/OpenDiablo2/d2audio"
|
"github.com/OpenDiablo2/OpenDiablo2/d2audio"
|
||||||
"github.com/OpenDiablo2/OpenDiablo2/d2core"
|
"github.com/OpenDiablo2/OpenDiablo2/d2core"
|
||||||
"github.com/OpenDiablo2/OpenDiablo2/d2corecommon/d2coreinterface"
|
"github.com/OpenDiablo2/OpenDiablo2/d2corecommon/d2coreinterface"
|
||||||
|
"github.com/OpenDiablo2/OpenDiablo2/d2player"
|
||||||
"github.com/OpenDiablo2/OpenDiablo2/d2render"
|
"github.com/OpenDiablo2/OpenDiablo2/d2render"
|
||||||
"github.com/OpenDiablo2/OpenDiablo2/d2render/d2mapengine"
|
"github.com/OpenDiablo2/OpenDiablo2/d2render/d2mapengine"
|
||||||
"github.com/OpenDiablo2/OpenDiablo2/d2render/d2ui"
|
"github.com/OpenDiablo2/OpenDiablo2/d2render/d2ui"
|
||||||
"github.com/hajimehoshi/ebiten"
|
"github.com/hajimehoshi/ebiten"
|
||||||
|
"image/color"
|
||||||
)
|
)
|
||||||
|
|
||||||
type Game struct {
|
type Game struct {
|
||||||
@ -28,6 +28,7 @@ type Game struct {
|
|||||||
testLabel d2ui.Label
|
testLabel d2ui.Label
|
||||||
mapEngine *d2mapengine.MapEngine
|
mapEngine *d2mapengine.MapEngine
|
||||||
hero *d2core.Hero
|
hero *d2core.Hero
|
||||||
|
gameControls *d2player.GameControls
|
||||||
}
|
}
|
||||||
|
|
||||||
func CreateGame(
|
func CreateGame(
|
||||||
@ -85,6 +86,10 @@ func (v *Game) Load() []func() {
|
|||||||
)
|
)
|
||||||
v.mapEngine.AddEntity(v.hero)
|
v.mapEngine.AddEntity(v.hero)
|
||||||
},
|
},
|
||||||
|
func() {
|
||||||
|
v.gameControls = d2player.NewGameControls(v.fileProvider, v.hero, v.mapEngine)
|
||||||
|
v.gameControls.Load()
|
||||||
|
},
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -94,6 +99,7 @@ func (v *Game) Unload() {
|
|||||||
func (v Game) Render(screen *ebiten.Image) {
|
func (v Game) Render(screen *ebiten.Image) {
|
||||||
screen.Fill(color.Black)
|
screen.Fill(color.Black)
|
||||||
v.mapEngine.Render(screen)
|
v.mapEngine.Render(screen)
|
||||||
|
v.gameControls.Render(screen)
|
||||||
}
|
}
|
||||||
|
|
||||||
func (v *Game) Update(tickTime float64) {
|
func (v *Game) Update(tickTime float64) {
|
||||||
@ -102,8 +108,5 @@ func (v *Game) Update(tickTime float64) {
|
|||||||
rx, ry := v.mapEngine.WorldToOrtho(v.hero.AnimatedEntity.LocationX/5, v.hero.AnimatedEntity.LocationY/5)
|
rx, ry := v.mapEngine.WorldToOrtho(v.hero.AnimatedEntity.LocationX/5, v.hero.AnimatedEntity.LocationY/5)
|
||||||
v.mapEngine.MoveCameraTo(rx, ry)
|
v.mapEngine.MoveCameraTo(rx, ry)
|
||||||
|
|
||||||
if ebiten.IsMouseButtonPressed(ebiten.MouseButtonLeft) {
|
v.gameControls.Move(tickTime)
|
||||||
px, py := v.mapEngine.ScreenToWorld(ebiten.CursorPosition())
|
|
||||||
v.hero.AnimatedEntity.SetTarget(px*5, py*5, 1)
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
@ -242,10 +242,12 @@ func (v Engine) Draw(screen *ebiten.Image) {
|
|||||||
ebitenutil.DebugPrintAt(screen, "vsync:"+strconv.FormatBool(ebiten.IsVsyncEnabled())+"\nFPS:"+strconv.Itoa(int(ebiten.CurrentFPS())), 5, 565)
|
ebitenutil.DebugPrintAt(screen, "vsync:"+strconv.FormatBool(ebiten.IsVsyncEnabled())+"\nFPS:"+strconv.Itoa(int(ebiten.CurrentFPS())), 5, 565)
|
||||||
var m runtime.MemStats
|
var m runtime.MemStats
|
||||||
runtime.ReadMemStats(&m)
|
runtime.ReadMemStats(&m)
|
||||||
ebitenutil.DebugPrintAt(screen, "Alloc "+strconv.FormatInt(int64(m.Alloc)/1024/1024, 10), 700, 0)
|
ebitenutil.DebugPrintAt(screen, "Alloc "+strconv.FormatInt(int64(m.Alloc)/1024/1024, 10), 680, 0)
|
||||||
ebitenutil.DebugPrintAt(screen, "Pause "+strconv.FormatInt(int64(m.PauseTotalNs/1024/1024), 10), 700, 10)
|
ebitenutil.DebugPrintAt(screen, "Pause "+strconv.FormatInt(int64(m.PauseTotalNs/1024/1024), 10), 680, 10)
|
||||||
ebitenutil.DebugPrintAt(screen, "HeapSys "+strconv.FormatInt(int64(m.HeapSys/1024/1024), 10), 700, 20)
|
ebitenutil.DebugPrintAt(screen, "HeapSys "+strconv.FormatInt(int64(m.HeapSys/1024/1024), 10), 680, 20)
|
||||||
ebitenutil.DebugPrintAt(screen, "NumGC "+strconv.FormatInt(int64(m.NumGC), 10), 700, 30)
|
ebitenutil.DebugPrintAt(screen, "NumGC "+strconv.FormatInt(int64(m.NumGC), 10), 680, 30)
|
||||||
|
cx, cy := ebiten.CursorPosition()
|
||||||
|
ebitenutil.DebugPrintAt(screen, "Coords "+strconv.FormatInt(int64(cx), 10) + ","+strconv.FormatInt(int64(cy), 10), 680, 40)
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
177
d2player/game_controls.go
Normal file
177
d2player/game_controls.go
Normal file
@ -0,0 +1,177 @@
|
|||||||
|
package d2player
|
||||||
|
|
||||||
|
import (
|
||||||
|
"github.com/OpenDiablo2/D2Shared/d2common/d2enum"
|
||||||
|
"github.com/OpenDiablo2/D2Shared/d2common/d2interface"
|
||||||
|
"github.com/OpenDiablo2/D2Shared/d2common/d2resource"
|
||||||
|
"github.com/OpenDiablo2/D2Shared/d2data/d2datadict"
|
||||||
|
"github.com/OpenDiablo2/D2Shared/d2data/d2dc6"
|
||||||
|
"github.com/OpenDiablo2/OpenDiablo2/d2core"
|
||||||
|
"github.com/OpenDiablo2/OpenDiablo2/d2render"
|
||||||
|
"github.com/OpenDiablo2/OpenDiablo2/d2render/d2mapengine"
|
||||||
|
"github.com/hajimehoshi/ebiten"
|
||||||
|
"log"
|
||||||
|
)
|
||||||
|
|
||||||
|
type GameControls struct {
|
||||||
|
fileProvider d2interface.FileProvider
|
||||||
|
hero *d2core.Hero
|
||||||
|
mapEngine *d2mapengine.MapEngine
|
||||||
|
|
||||||
|
// UI
|
||||||
|
globeSprite *d2render.Sprite
|
||||||
|
mainPanel *d2render.Sprite
|
||||||
|
menuButton *d2render.Sprite
|
||||||
|
skillIcon *d2render.Sprite
|
||||||
|
}
|
||||||
|
|
||||||
|
func NewGameControls(fileProvider d2interface.FileProvider, hero *d2core.Hero, mapEngine *d2mapengine.MapEngine) *GameControls {
|
||||||
|
return &GameControls{
|
||||||
|
fileProvider: fileProvider,
|
||||||
|
hero: hero,
|
||||||
|
mapEngine: mapEngine,
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
func (g *GameControls) Move(tickTime float64) {
|
||||||
|
|
||||||
|
if ebiten.IsMouseButtonPressed(ebiten.MouseButtonLeft) {
|
||||||
|
px, py := g.mapEngine.ScreenToWorld(ebiten.CursorPosition())
|
||||||
|
g.hero.AnimatedEntity.SetTarget(px*5, py*5, 1)
|
||||||
|
}
|
||||||
|
|
||||||
|
arrowDistance := 1.0
|
||||||
|
moveX := 0.0
|
||||||
|
moveY := 0.0
|
||||||
|
if ebiten.IsKeyPressed(ebiten.KeyW) || ebiten.IsKeyPressed(ebiten.KeyUp) {
|
||||||
|
moveY -= arrowDistance
|
||||||
|
moveX -= arrowDistance
|
||||||
|
}
|
||||||
|
if ebiten.IsKeyPressed(ebiten.KeyS) || ebiten.IsKeyPressed(ebiten.KeyDown) {
|
||||||
|
moveY += arrowDistance
|
||||||
|
moveX += arrowDistance
|
||||||
|
}
|
||||||
|
if ebiten.IsKeyPressed(ebiten.KeyA) || ebiten.IsKeyPressed(ebiten.KeyLeft) {
|
||||||
|
moveY += arrowDistance
|
||||||
|
moveX -= arrowDistance
|
||||||
|
}
|
||||||
|
if ebiten.IsKeyPressed(ebiten.KeyD) || ebiten.IsKeyPressed(ebiten.KeyRight) {
|
||||||
|
moveY -= arrowDistance
|
||||||
|
moveX += arrowDistance
|
||||||
|
}
|
||||||
|
|
||||||
|
if moveY != 0 || moveX != 0 {
|
||||||
|
g.hero.AnimatedEntity.SetTarget(g.hero.AnimatedEntity.LocationX+moveX, g.hero.AnimatedEntity.LocationY+moveY, 1)
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
func (g *GameControls) Load() {
|
||||||
|
dc6, err := d2dc6.LoadDC6(g.fileProvider.LoadFile(d2resource.GameGlobeOverlap), d2datadict.Palettes[d2enum.Sky])
|
||||||
|
if err != nil {
|
||||||
|
log.Panicf("failed to load %s: %v", d2resource.GameGlobeOverlap, err)
|
||||||
|
}
|
||||||
|
globeSprite := d2render.CreateSpriteFromDC6(dc6)
|
||||||
|
g.globeSprite = &globeSprite
|
||||||
|
|
||||||
|
dc6, err = d2dc6.LoadDC6(g.fileProvider.LoadFile(d2resource.GamePanels), d2datadict.Palettes[d2enum.Sky])
|
||||||
|
if err != nil {
|
||||||
|
log.Panicf("failed to load %s: %v", d2resource.GamePanels, err)
|
||||||
|
}
|
||||||
|
mainPanel := d2render.CreateSpriteFromDC6(dc6)
|
||||||
|
g.mainPanel = &mainPanel
|
||||||
|
|
||||||
|
dc6, err = d2dc6.LoadDC6(g.fileProvider.LoadFile(d2resource.MenuButton), d2datadict.Palettes[d2enum.Sky])
|
||||||
|
if err != nil {
|
||||||
|
log.Panicf("failed to load %s: %v", d2resource.MenuButton, err)
|
||||||
|
}
|
||||||
|
menuButton := d2render.CreateSpriteFromDC6(dc6)
|
||||||
|
g.menuButton = &menuButton
|
||||||
|
|
||||||
|
dc6, err = d2dc6.LoadDC6(g.fileProvider.LoadFile(d2resource.GenericSkills), d2datadict.Palettes[d2enum.Sky])
|
||||||
|
if err != nil {
|
||||||
|
log.Panicf("failed to load %s: %v", d2resource.GenericSkills, err)
|
||||||
|
}
|
||||||
|
skillIcon := d2render.CreateSpriteFromDC6(dc6)
|
||||||
|
g.skillIcon = &skillIcon
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
// TODO: consider caching the panels to single image that is reused.
|
||||||
|
func (g *GameControls) Render(target *ebiten.Image) {
|
||||||
|
width, height := target.Size()
|
||||||
|
offset := uint32(0)
|
||||||
|
|
||||||
|
// Left globe holder
|
||||||
|
g.mainPanel.Frame = 0
|
||||||
|
w, _ := g.mainPanel.GetSize()
|
||||||
|
g.mainPanel.MoveTo(int(offset), height)
|
||||||
|
g.mainPanel.Draw(target)
|
||||||
|
|
||||||
|
// Left globe
|
||||||
|
g.globeSprite.Frame = 0
|
||||||
|
g.globeSprite.MoveTo(int(offset+28), height - 5)
|
||||||
|
g.globeSprite.Draw(target)
|
||||||
|
offset += w
|
||||||
|
|
||||||
|
// Left skill
|
||||||
|
g.skillIcon.Frame = 2
|
||||||
|
w, _ = g.skillIcon.GetSize()
|
||||||
|
g.skillIcon.MoveTo(int(offset), height)
|
||||||
|
g.skillIcon.Draw(target)
|
||||||
|
offset += w
|
||||||
|
|
||||||
|
// Left skill selector
|
||||||
|
g.mainPanel.Frame = 1
|
||||||
|
w, _ = g.mainPanel.GetSize()
|
||||||
|
g.mainPanel.MoveTo(int(offset), height)
|
||||||
|
g.mainPanel.Draw(target)
|
||||||
|
offset += w
|
||||||
|
|
||||||
|
// Stamina
|
||||||
|
g.mainPanel.Frame = 2
|
||||||
|
w, _ = g.mainPanel.GetSize()
|
||||||
|
g.mainPanel.MoveTo(int(offset), height)
|
||||||
|
g.mainPanel.Draw(target)
|
||||||
|
offset += w
|
||||||
|
|
||||||
|
// Center menu button
|
||||||
|
g.menuButton.Frame = 0
|
||||||
|
w, _ = g.mainPanel.GetSize()
|
||||||
|
g.menuButton.MoveTo((width / 2) - 8 , height - 16)
|
||||||
|
g.menuButton.Draw(target)
|
||||||
|
|
||||||
|
// Potions
|
||||||
|
g.mainPanel.Frame = 3
|
||||||
|
w, _ = g.mainPanel.GetSize()
|
||||||
|
g.mainPanel.MoveTo(int(offset), height)
|
||||||
|
g.mainPanel.Draw(target)
|
||||||
|
offset += w
|
||||||
|
|
||||||
|
// Right skill selector
|
||||||
|
g.mainPanel.Frame = 4
|
||||||
|
w, _ = g.mainPanel.GetSize()
|
||||||
|
g.mainPanel.MoveTo(int(offset), height)
|
||||||
|
g.mainPanel.Draw(target)
|
||||||
|
offset += w
|
||||||
|
|
||||||
|
// Right skill
|
||||||
|
g.skillIcon.Frame = 10
|
||||||
|
w, _ = g.skillIcon.GetSize()
|
||||||
|
g.skillIcon.MoveTo(int(offset), height)
|
||||||
|
g.skillIcon.Draw(target)
|
||||||
|
offset += w
|
||||||
|
|
||||||
|
// Right globe holder
|
||||||
|
g.mainPanel.Frame = 5
|
||||||
|
w, _ = g.mainPanel.GetSize()
|
||||||
|
g.mainPanel.MoveTo(int(offset), height)
|
||||||
|
g.mainPanel.Draw(target)
|
||||||
|
|
||||||
|
// Right globe
|
||||||
|
g.globeSprite.Frame = 1
|
||||||
|
g.globeSprite.MoveTo(int(offset) + 8, height - 8)
|
||||||
|
g.globeSprite.Draw(target)
|
||||||
|
|
||||||
|
}
|
Loading…
Reference in New Issue
Block a user