1
1
mirror of https://github.com/OpenDiablo2/OpenDiablo2 synced 2025-02-03 23:26:41 -05:00

Adding input system, mouse cursor scene, interactive component

* added `d2common/d2input`, copied input vector logic from hellspawner
* added an `InteractiveComponent` which contains input vector, enable
flag, and callback function
* Added an InputSystem which handles input logic and iterates over
entities with interactive components
* added a mouse cursor scene for rendering the mouse cursor
* made the trademark sprite disappear when left mouse is clicked
* various other small bugfixes in scene systems
This commit is contained in:
gravestench 2020-11-28 15:49:18 -08:00
parent 3f5d2c0938
commit e6d418fdb2
12 changed files with 582 additions and 18 deletions

View File

@ -0,0 +1,93 @@
package d2input
import "github.com/gravestench/akara"
func NewInputVector() *InputVector {
v := &InputVector{
KeyVector: akara.NewBitSet(),
ModifierVector: akara.NewBitSet(),
MouseButtonVector: akara.NewBitSet(),
}
return v.Clear()
}
type InputVector struct {
KeyVector *akara.BitSet
ModifierVector *akara.BitSet
MouseButtonVector *akara.BitSet
}
func (iv *InputVector) SetKey(key Key) *InputVector {
return iv.SetKeys([]Key{key})
}
func (iv *InputVector) SetKeys(keys []Key) *InputVector {
if len(keys) == 0 {
return iv
}
for _, key := range keys {
iv.KeyVector.Set(int(key), true)
}
return iv
}
func (iv *InputVector) SetModifier(mod Modifier) *InputVector {
return iv.SetModifiers([]Modifier{mod})
}
func (iv *InputVector) SetModifiers(mods []Modifier) *InputVector {
if len(mods) == 0 {
return iv
}
for _, key := range mods {
iv.ModifierVector.Set(int(key), true)
}
return iv
}
func (iv *InputVector) SetMouseButton(button MouseButton) *InputVector {
return iv.SetMouseButtons([]MouseButton{button})
}
func (iv *InputVector) SetMouseButtons(buttons []MouseButton) *InputVector {
if len(buttons) == 0 {
return iv
}
for _, key := range buttons {
iv.MouseButtonVector.Set(int(key), true)
}
return iv
}
func (iv *InputVector) Contains(other *InputVector) bool {
keys := iv.KeyVector.ContainsAll(other.KeyVector)
buttons := iv.MouseButtonVector.ContainsAll(other.MouseButtonVector)
// We do Equals here, because we dont want CTRL+X and CTRL+ALT+X to fire at the same time
mods := iv.ModifierVector.Equals(other.ModifierVector)
return keys && mods && buttons
}
func (iv *InputVector) Intersects(other *InputVector) bool {
keys := iv.KeyVector.Intersects(other.KeyVector)
mods := iv.ModifierVector.Intersects(other.ModifierVector)
buttons := iv.MouseButtonVector.Intersects(other.MouseButtonVector)
return keys || mods || buttons
}
func (iv *InputVector) Clear() *InputVector {
iv.KeyVector.Clear()
iv.ModifierVector.Clear()
iv.MouseButtonVector.Clear()
return iv
}

105
d2common/d2input/keys.go Normal file
View File

@ -0,0 +1,105 @@
package d2input
import "github.com/hajimehoshi/ebiten/v2"
type Key = int
const (
Key0 = Key(ebiten.Key0)
Key1 = Key(ebiten.Key1)
Key2 = Key(ebiten.Key2)
Key3 = Key(ebiten.Key3)
Key4 = Key(ebiten.Key4)
Key5 = Key(ebiten.Key5)
Key6 = Key(ebiten.Key6)
Key7 = Key(ebiten.Key7)
Key8 = Key(ebiten.Key8)
Key9 = Key(ebiten.Key9)
KeyA = Key(ebiten.KeyA)
KeyB = Key(ebiten.KeyB)
KeyC = Key(ebiten.KeyC)
KeyD = Key(ebiten.KeyD)
KeyE = Key(ebiten.KeyE)
KeyF = Key(ebiten.KeyF)
KeyG = Key(ebiten.KeyG)
KeyH = Key(ebiten.KeyH)
KeyI = Key(ebiten.KeyI)
KeyJ = Key(ebiten.KeyJ)
KeyK = Key(ebiten.KeyK)
KeyL = Key(ebiten.KeyL)
KeyM = Key(ebiten.KeyM)
KeyN = Key(ebiten.KeyN)
KeyO = Key(ebiten.KeyO)
KeyP = Key(ebiten.KeyP)
KeyQ = Key(ebiten.KeyQ)
KeyR = Key(ebiten.KeyR)
KeyS = Key(ebiten.KeyS)
KeyT = Key(ebiten.KeyT)
KeyU = Key(ebiten.KeyU)
KeyV = Key(ebiten.KeyV)
KeyW = Key(ebiten.KeyW)
KeyX = Key(ebiten.KeyX)
KeyY = Key(ebiten.KeyY)
KeyZ = Key(ebiten.KeyZ)
KeyApostrophe = Key(ebiten.KeyApostrophe)
KeyBackslash = Key(ebiten.KeyBackslash)
KeyBackspace = Key(ebiten.KeyBackspace)
KeyCapsLock = Key(ebiten.KeyCapsLock)
KeyComma = Key(ebiten.KeyComma)
KeyDelete = Key(ebiten.KeyDelete)
KeyDown = Key(ebiten.KeyDown)
KeyEnd = Key(ebiten.KeyEnd)
KeyEnter = Key(ebiten.KeyEnter)
KeyEqual = Key(ebiten.KeyEqual)
KeyEscape = Key(ebiten.KeyEscape)
KeyF1 = Key(ebiten.KeyF1)
KeyF2 = Key(ebiten.KeyF2)
KeyF3 = Key(ebiten.KeyF3)
KeyF4 = Key(ebiten.KeyF4)
KeyF5 = Key(ebiten.KeyF5)
KeyF6 = Key(ebiten.KeyF6)
KeyF7 = Key(ebiten.KeyF7)
KeyF8 = Key(ebiten.KeyF8)
KeyF9 = Key(ebiten.KeyF9)
KeyF10 = Key(ebiten.KeyF10)
KeyF11 = Key(ebiten.KeyF11)
KeyF12 = Key(ebiten.KeyF12)
KeyGraveAccent = Key(ebiten.KeyGraveAccent)
KeyHome = Key(ebiten.KeyHome)
KeyInsert = Key(ebiten.KeyInsert)
KeyKP0 = Key(ebiten.KeyKP0)
KeyKP1 = Key(ebiten.KeyKP1)
KeyKP2 = Key(ebiten.KeyKP2)
KeyKP3 = Key(ebiten.KeyKP3)
KeyKP4 = Key(ebiten.KeyKP4)
KeyKP5 = Key(ebiten.KeyKP5)
KeyKP6 = Key(ebiten.KeyKP6)
KeyKP7 = Key(ebiten.KeyKP7)
KeyKP8 = Key(ebiten.KeyKP8)
KeyKP9 = Key(ebiten.KeyKP9)
KeyKPAdd = Key(ebiten.KeyKPAdd)
KeyKPDecimal = Key(ebiten.KeyKPDecimal)
KeyKPDivide = Key(ebiten.KeyKPDivide)
KeyKPEnter = Key(ebiten.KeyKPEnter)
KeyKPEqual = Key(ebiten.KeyKPEqual)
KeyKPMultiply = Key(ebiten.KeyKPMultiply)
KeyKPSubtract = Key(ebiten.KeyKPSubtract)
KeyLeft = Key(ebiten.KeyLeft)
KeyLeftBracket = Key(ebiten.KeyLeftBracket)
KeyMenu = Key(ebiten.KeyMenu)
KeyMinus = Key(ebiten.KeyMinus)
KeyNumLock = Key(ebiten.KeyNumLock)
KeyPageDown = Key(ebiten.KeyPageDown)
KeyPageUp = Key(ebiten.KeyPageUp)
KeyPause = Key(ebiten.KeyPause)
KeyPeriod = Key(ebiten.KeyPeriod)
KeyPrintScreen = Key(ebiten.KeyPrintScreen)
KeyRight = Key(ebiten.KeyRight)
KeyRightBracket = Key(ebiten.KeyRightBracket)
KeyScrollLock = Key(ebiten.KeyScrollLock)
KeySemicolon = Key(ebiten.KeySemicolon)
KeySlash = Key(ebiten.KeySlash)
KeySpace = Key(ebiten.KeySpace)
KeyTab = Key(ebiten.KeyTab)
KeyUp = Key(ebiten.KeyUp)
)

View File

@ -0,0 +1,11 @@
package d2input
import "github.com/hajimehoshi/ebiten/v2"
type Modifier = int
const (
ModAlt = Modifier(ebiten.KeyAlt)
ModControl = Modifier(ebiten.KeyControl)
ModShift = Modifier(ebiten.KeyShift)
)

View File

@ -0,0 +1,11 @@
package d2input
import "github.com/hajimehoshi/ebiten/v2"
type MouseButton = int
const (
MouseButtonLeft = MouseButton(ebiten.MouseButtonLeft)
MouseButtonRight = MouseButton(ebiten.MouseButtonRight)
MouseButtonMiddle = MouseButton(ebiten.MouseButtonMiddle)
)

View File

@ -0,0 +1,51 @@
package d2components
import (
"github.com/gravestench/akara"
"github.com/OpenDiablo2/OpenDiablo2/d2common/d2input"
)
// static check that Interactive implements Component
var _ akara.Component = &Interactive{}
func noop() bool {
return false
}
// Interactive is used to flag file entities with a file type
type Interactive struct {
Enabled bool
*d2input.InputVector
Callback func() (preventPropagation bool)
}
// New returns a Interactive component. By default, it contains a nil instance.
func (*Interactive) New() akara.Component {
return &Interactive{
Enabled: true,
InputVector: d2input.NewInputVector(),
Callback: noop,
}
}
// InteractiveFactory is a wrapper for the generic component factory that returns Interactive component instances.
// This can be embedded inside of a system to give them the methods for adding, retrieving, and removing a Interactive.
type InteractiveFactory struct {
Interactive *akara.ComponentFactory
}
// AddInteractive adds a Interactive component to the given entity and returns it
func (m *InteractiveFactory) AddInteractive(id akara.EID) *Interactive {
return m.Interactive.Add(id).(*Interactive)
}
// GetInteractive returns the Interactive component for the given entity, and a bool for whether or not it exists
func (m *InteractiveFactory) GetInteractive(id akara.EID) (*Interactive, bool) {
component, found := m.Interactive.Get(id)
if !found {
return nil, found
}
return component.(*Interactive), found
}

View File

@ -46,6 +46,9 @@ func (m *GameClientBootstrapSystem) injectSystems() {
m.Info("injecting render system")
m.AddSystem(&RenderSystem{})
m.Info("injecting input system")
m.AddSystem(&InputSystem{})
m.Info("injecting update counter system")
m.AddSystem(&UpdateCounter{})
@ -54,6 +57,9 @@ func (m *GameClientBootstrapSystem) injectSystems() {
m.Info("injecting main menu scene")
m.AddSystem(NewMainMenuScene())
m.Info("injecting mouse cursor scene")
m.AddSystem(NewMouseCursorScene())
}
// Update does nothing, but exists to satisfy the `akara.System` interface

View File

@ -0,0 +1,151 @@
package d2systems
import (
"github.com/OpenDiablo2/OpenDiablo2/d2common/d2input"
"github.com/hajimehoshi/ebiten/v2"
"github.com/OpenDiablo2/OpenDiablo2/d2common/d2interface"
"github.com/OpenDiablo2/OpenDiablo2/d2common/d2util"
"github.com/OpenDiablo2/OpenDiablo2/d2core/d2components"
"github.com/gravestench/akara"
)
const (
logPrefixInputSystem = "Input System"
)
// static check that InputSystem implements the System interface
var _ akara.System = &InputSystem{}
// InputSystem is responsible for handling interactive entities
type InputSystem struct {
akara.BaseSubscriberSystem
*d2util.Logger
renderer d2interface.Renderer
configs *akara.Subscription
interactives *akara.Subscription
d2components.GameConfigFactory
d2components.InteractiveFactory
inputState *d2input.InputVector
}
// Init initializes the system with the given world, injecting the necessary components
func (m *InputSystem) Init(world *akara.World) {
m.World = world
m.setupLogger()
m.Info("initializing ...")
m.setupFactories()
m.setupSubscriptions()
m.inputState = d2input.NewInputVector()
}
func (m *InputSystem) setupLogger() {
m.Logger = d2util.NewLogger()
m.SetPrefix(logPrefixInputSystem)
}
func (m *InputSystem) setupFactories() {
m.Info("setting up component factories")
gameConfigID := m.RegisterComponent(&d2components.GameConfig{})
interactiveID := m.RegisterComponent(&d2components.Interactive{})
m.GameConfig = m.GetComponentFactory(gameConfigID)
m.Interactive = m.GetComponentFactory(interactiveID)
}
func (m *InputSystem) setupSubscriptions() {
m.Info("setting up component subscriptions")
interactives := m.NewComponentFilter().
Require(&d2components.Interactive{}).
Build()
gameConfigs := m.NewComponentFilter().
Require(&d2components.GameConfig{}).
Build()
m.interactives = m.AddSubscription(interactives)
m.configs = m.AddSubscription(gameConfigs)
}
// Update will iterate over interactive entities
func (m *InputSystem) Update() {
m.updateInputState()
for _, id := range m.interactives.GetEntities() {
preventPropagation := m.applyInputState(id)
if preventPropagation {
break
}
}
}
func (m *InputSystem) updateInputState() {
var keysToCheck = []d2input.Key{
d2input.Key0, d2input.Key1, d2input.Key2, d2input.Key3, d2input.Key4, d2input.Key5, d2input.Key6,
d2input.Key7, d2input.Key8, d2input.Key9, d2input.KeyA, d2input.KeyB, d2input.KeyC, d2input.KeyD,
d2input.KeyE, d2input.KeyF, d2input.KeyG, d2input.KeyH, d2input.KeyI, d2input.KeyJ, d2input.KeyK,
d2input.KeyL, d2input.KeyM, d2input.KeyN, d2input.KeyO, d2input.KeyP, d2input.KeyQ, d2input.KeyR,
d2input.KeyS, d2input.KeyT, d2input.KeyU, d2input.KeyV, d2input.KeyW, d2input.KeyX, d2input.KeyY,
d2input.KeyZ, d2input.KeyApostrophe, d2input.KeyBackslash, d2input.KeyBackspace,
d2input.KeyCapsLock, d2input.KeyComma, d2input.KeyDelete, d2input.KeyDown,
d2input.KeyEnd, d2input.KeyEnter, d2input.KeyEqual, d2input.KeyEscape,
d2input.KeyF1, d2input.KeyF2, d2input.KeyF3, d2input.KeyF4, d2input.KeyF5, d2input.KeyF6,
d2input.KeyF7, d2input.KeyF8, d2input.KeyF9, d2input.KeyF10, d2input.KeyF11, d2input.KeyF12,
d2input.KeyGraveAccent, d2input.KeyHome, d2input.KeyInsert, d2input.KeyKP0,
d2input.KeyKP1, d2input.KeyKP2, d2input.KeyKP3, d2input.KeyKP4, d2input.KeyKP5,
d2input.KeyKP6, d2input.KeyKP7, d2input.KeyKP8, d2input.KeyKP9,
d2input.KeyKPAdd, d2input.KeyKPDecimal, d2input.KeyKPDivide, d2input.KeyKPEnter,
d2input.KeyKPEqual, d2input.KeyKPMultiply, d2input.KeyKPSubtract, d2input.KeyLeft,
d2input.KeyLeftBracket, d2input.KeyMenu, d2input.KeyMinus, d2input.KeyNumLock,
d2input.KeyPageDown, d2input.KeyPageUp, d2input.KeyPause, d2input.KeyPeriod,
d2input.KeyPrintScreen, d2input.KeyRight, d2input.KeyRightBracket,
d2input.KeyScrollLock, d2input.KeySemicolon, d2input.KeySlash,
d2input.KeySpace, d2input.KeyTab, d2input.KeyUp,
}
var modifiersToCheck = []d2input.Modifier{
d2input.ModAlt, d2input.ModControl, d2input.ModShift,
}
var buttonsToCheck = []d2input.MouseButton{
d2input.MouseButtonLeft, d2input.MouseButtonMiddle, d2input.MouseButtonRight,
}
for _, key := range keysToCheck {
truth := ebiten.IsKeyPressed(ebiten.Key(key))
m.inputState.KeyVector.Set(key, truth)
}
for _, mod := range modifiersToCheck {
truth := ebiten.IsKeyPressed(ebiten.Key(mod))
m.inputState.ModifierVector.Set(mod, truth)
}
for _, btn := range buttonsToCheck {
truth := ebiten.IsMouseButtonPressed(ebiten.MouseButton(btn))
m.inputState.MouseButtonVector.Set(btn, truth)
}
}
func (m *InputSystem) applyInputState(id akara.EID) (preventPropagation bool) {
v, found := m.GetInteractive(id)
if !found {
return false
}
if !v.Enabled {
return
}
if m.inputState.Contains(v.InputVector) {
return v.Callback()
}
return false
}

View File

@ -37,6 +37,7 @@ var _ akara.System = &BaseScene{}
type baseSystems struct {
*RenderSystem
*InputSystem
*GameObjectFactory
}
@ -58,8 +59,10 @@ type BaseScene struct {
d2components.ViewportFactory
d2components.MainViewportFactory
d2components.ViewportFilterFactory
d2components.PriorityFactory
d2components.CameraFactory
d2components.RenderableFactory
d2components.InteractiveFactory
d2components.PositionFactory
d2components.ScaleFactory
d2components.AnimationFactory
@ -82,6 +85,7 @@ func (s *BaseScene) Init(world *akara.World) {
s.World = world
if s.World == nil {
s.SetActive(false)
return
}
}
@ -99,12 +103,17 @@ func (s *BaseScene) boot() {
s.Add.SetPrefix(fmt.Sprintf("%s -> %s", s.key, "Object Factory"))
for idx := range s.Systems {
if rendersys, ok := s.Systems[idx].(*RenderSystem); ok {
if rendersys, ok := s.Systems[idx].(*RenderSystem); ok && s.systems.RenderSystem == nil {
s.systems.RenderSystem = rendersys
continue
}
if objFactory, ok := s.Systems[idx].(*GameObjectFactory); ok {
if inputSys, ok := s.Systems[idx].(*InputSystem); ok && s.systems.InputSystem == nil {
s.systems.InputSystem = inputSys
continue
}
if objFactory, ok := s.Systems[idx].(*GameObjectFactory); ok && s.systems.GameObjectFactory == nil {
s.systems.GameObjectFactory = objFactory
continue
}
@ -120,6 +129,13 @@ func (s *BaseScene) boot() {
return
}
if s.systems.InputSystem == nil {
s.Info("waiting for input system")
return
}
s.systems.InputSystem.renderer = s.systems.RenderSystem.renderer
if s.systems.GameObjectFactory == nil {
s.Info("waiting for game object factory ...")
return
@ -140,7 +156,9 @@ func (s *BaseScene) setupFactories() {
viewportID := s.RegisterComponent(&d2components.Viewport{})
viewportFilterID := s.RegisterComponent(&d2components.ViewportFilter{})
cameraID := s.RegisterComponent(&d2components.Camera{})
priorityID := s.RegisterComponent(&d2components.Priority{})
renderableID := s.RegisterComponent(&d2components.Renderable{})
interactiveID := s.RegisterComponent(&d2components.Interactive{})
positionID := s.RegisterComponent(&d2components.Position{})
scaleID := s.RegisterComponent(&d2components.Scale{})
animationID := s.RegisterComponent(&d2components.Animation{})
@ -151,7 +169,9 @@ func (s *BaseScene) setupFactories() {
s.Viewport = s.GetComponentFactory(viewportID)
s.ViewportFilter = s.GetComponentFactory(viewportFilterID)
s.Camera = s.GetComponentFactory(cameraID)
s.Priority = s.GetComponentFactory(priorityID)
s.Renderable = s.GetComponentFactory(renderableID)
s.Interactive = s.GetComponentFactory(interactiveID)
s.Position = s.GetComponentFactory(positionID)
s.Scale = s.GetComponentFactory(scaleID)
s.Animation = s.GetComponentFactory(animationID)
@ -163,13 +183,11 @@ func (s *BaseScene) createDefaultViewport() {
s.Info("creating default viewport")
viewportID := s.NewEntity()
s.AddViewport(viewportID)
s.AddPriority(viewportID)
camera := s.AddCamera(viewportID)
camera.Width = 800
camera.Height = 600
camera.Zoom = 1
sfc := s.systems.renderer.NewSurface(camera.Width, camera.Height)
sfc := s.systems.RenderSystem.renderer.NewSurface(camera.Width, camera.Height)
sfc.Clear(color.Transparent)
@ -266,9 +284,11 @@ func (s *BaseScene) renderViewport(idx int, objects []akara.EID) {
}
if sfc.Surface == nil {
sfc.Surface = s.systems.renderer.NewSurface(camera.Width, camera.Height)
sfc.Surface = s.systems.RenderSystem.renderer.NewSurface(camera.Width, camera.Height)
}
sfc.Clear(color.Transparent)
cx, cy := int(camera.X()), int(camera.Y())
sfc.Surface.PushTranslation(cx, cy) // negative because we're offsetting everything that gets rendered
@ -298,6 +318,11 @@ func (s *BaseScene) renderObject(target d2interface.Surface, id akara.EID) {
scale = s.AddScale(id)
}
alpha, found := s.GetAlpha(id)
if !found {
alpha = s.AddAlpha(id)
}
x, y := int(position.X()), int(position.Y())
target.PushTranslation(x, y)
@ -306,6 +331,9 @@ func (s *BaseScene) renderObject(target d2interface.Surface, id akara.EID) {
target.PushScale(scale.X(), scale.Y())
defer target.Pop()
target.PushColor(color.Alpha{A: uint8(alpha.Alpha * 255)})
defer target.Pop()
segment, found := s.systems.SpriteFactory.GetSegmentedSprite(id)
if found {
animation, found := s.GetAnimation(id)
@ -352,10 +380,10 @@ type sceneObjectFactory struct {
}
func (s *sceneObjectFactory) addBasicComponenets(id akara.EID) {
_ = s.AddScale(id)
_ = s.AddOrigin(id)
_ = s.AddPosition(id)
_ = s.AddScale(id)
_ = s.AddAlpha(id)
_ = s.AddOrigin(id)
}
func (s *sceneObjectFactory) Sprite(x, y float64, imgPath, palPath string) akara.EID {

View File

@ -72,6 +72,7 @@ func (s *LoadingScene) Init(world *akara.World) {
func (s *LoadingScene) boot() {
if !s.BaseScene.booted {
s.BaseScene.boot()
return
}

View File

@ -1,6 +1,7 @@
package d2systems
import (
"github.com/OpenDiablo2/OpenDiablo2/d2common/d2input"
"github.com/gravestench/akara"
"github.com/OpenDiablo2/OpenDiablo2/d2common/d2interface"
@ -28,7 +29,11 @@ var _ d2interface.Scene = &MainMenuScene{}
// or start the map engine test.
type MainMenuScene struct {
*BaseScene
booted bool
booted bool
sprites struct {
trademark akara.EID
mainBackground akara.EID
}
}
// Init the main menu scene
@ -43,16 +48,20 @@ func (s *MainMenuScene) boot() {
return
}
s.createTrademarkScreen()
s.createButtons()
s.createBackground()
s.createButtons()
s.createTrademarkScreen()
s.booted = true
}
func (s *MainMenuScene) createBackground() {
s.Info("creating background")
s.Add.SegmentedSprite(0, 0, d2resource.GameSelectScreen, d2resource.PaletteSky, 4, 3, 0)
imgPath := d2resource.GameSelectScreen
palPath := d2resource.PaletteSky
s.sprites.mainBackground = s.Add.SegmentedSprite(0, 0, imgPath, palPath, 4, 3, 0)
}
func (s *MainMenuScene) createButtons() {
@ -61,7 +70,26 @@ func (s *MainMenuScene) createButtons() {
func (s *MainMenuScene) createTrademarkScreen() {
s.Info("creating trademark screen")
s.Add.SegmentedSprite(0, 0, d2resource.TrademarkScreen, d2resource.PaletteSky, 4, 3, 0)
imgPath := d2resource.TrademarkScreen
palPath := d2resource.PaletteSky
s.sprites.trademark = s.Add.SegmentedSprite(0, 0, imgPath, palPath, 4, 3, 0)
interactive := s.AddInteractive(s.sprites.trademark)
interactive.InputVector.SetMouseButton(d2input.MouseButtonLeft)
interactive.Callback = func() bool {
s.Info("hiding trademark sprite")
alpha, _ := s.GetAlpha(s.sprites.trademark)
alpha.Alpha = 0
interactive.Enabled = false
return true // prevent propagation
}
}
// Update the main menu scene

View File

@ -0,0 +1,83 @@
package d2systems
import (
"github.com/gravestench/akara"
"github.com/OpenDiablo2/OpenDiablo2/d2common/d2interface"
"github.com/OpenDiablo2/OpenDiablo2/d2common/d2resource"
)
const (
sceneKeyMouseCursor = "Mouse Cursor"
)
// NewMouseCursorScene creates a new main menu scene. This is the first screen that the user
// will see when launching the game.
func NewMouseCursorScene() *MouseCursorScene {
scene := &MouseCursorScene{
BaseScene: NewBaseScene(sceneKeyMouseCursor),
}
return scene
}
// static check that MouseCursorScene implements the scene interface
var _ d2interface.Scene = &MouseCursorScene{}
// MouseCursorScene represents the game's main menu, where users can select single or multi player,
// or start the map engine test.
type MouseCursorScene struct {
*BaseScene
booted bool
cursor akara.EID
}
// Init the main menu scene
func (s *MouseCursorScene) Init(world *akara.World) {
s.World = world
s.Info("initializing ...")
}
func (s *MouseCursorScene) boot() {
if !s.BaseScene.booted {
s.BaseScene.boot()
return
}
s.createMouseCursor()
s.booted = true
}
func (s *MouseCursorScene) createMouseCursor() {
s.Info("creating mouse cursor")
s.cursor = s.Add.Sprite(0, 0, d2resource.CursorDefault, d2resource.PaletteUnits)
}
// Update the main menu scene
func (s *MouseCursorScene) Update() {
if s.Paused() {
return
}
if !s.booted {
s.boot()
return
}
s.updateCursorPosition()
s.BaseScene.Update()
}
func (s *MouseCursorScene) updateCursorPosition() {
spritePosition, found := s.GetPosition(s.cursor)
if !found {
return
}
cx, cy := s.systems.InputSystem.renderer.GetCursorPos()
spritePosition.Set(float64(cx), float64(cy))
}

4
go.sum
View File

@ -19,10 +19,6 @@ github.com/gofrs/flock v0.8.0 h1:MSdYClljsF3PbENUUEx85nkWfJSGfzYI9yEBZOJz6CY=
github.com/gofrs/flock v0.8.0/go.mod h1:F1TvTiK9OcQqauNUHlbJvyl9Qa1QvF/gOUDKA14jxHU=
github.com/google/uuid v1.1.2 h1:EVhdT+1Kseyi1/pUmXKaFxYsDNy9RQYkMWRH68J/W7Y=
github.com/google/uuid v1.1.2/go.mod h1:TIyPZe4MgqvfeYDBFedMoGGpEw/LqOeaOT+nhxU+yHo=
github.com/gravestench/akara v0.0.0-20201119221449-924b47999403 h1:hoCEhoSD+4Hvg3xdbfbVleJXhyHqP/1jUa1QqexE1UQ=
github.com/gravestench/akara v0.0.0-20201119221449-924b47999403/go.mod h1:fTeda1SogMg5Lkd4lXMEd/Pk/a5/gQuLGaAI2rn1PBQ=
github.com/gravestench/akara v0.0.0-20201122210148-a1ee8ea83994 h1:Wp+4kZ0Pkap2ueAkTrE22rk++3VZE8TsU1bewpnzmsM=
github.com/gravestench/akara v0.0.0-20201122210148-a1ee8ea83994/go.mod h1:fTeda1SogMg5Lkd4lXMEd/Pk/a5/gQuLGaAI2rn1PBQ=
github.com/gravestench/akara v0.0.0-20201128054238-892de9d70d6b h1:Ngfdn7O3wXQBzbOLsL6vQ9G4F7utUiKjQqKnwHbY5uI=
github.com/gravestench/akara v0.0.0-20201128054238-892de9d70d6b/go.mod h1:fTeda1SogMg5Lkd4lXMEd/Pk/a5/gQuLGaAI2rn1PBQ=
github.com/hajimehoshi/bitmapfont/v2 v2.1.0/go.mod h1:2BnYrkTQGThpr/CY6LorYtt/zEPNzvE/ND69CRTaHMs=