mirror of
https://github.com/OpenDiablo2/OpenDiablo2
synced 2025-02-05 08:07:51 -05:00
Minor edits: debug entity frame bounds, debug spawnmon
command (#666)
* adding debug printing boxes for entity bounds * minor edits - adding `spawnmon` command. currently does not have a netpacket, just for debug - adding `GetSize` method to map entities for getting frame bounds (for debug printing) * bug fix
This commit is contained in:
parent
6514fd15de
commit
6a8b9aada1
@ -8,6 +8,7 @@ type MapEntity interface {
|
|||||||
Advance(tickTime float64)
|
Advance(tickTime float64)
|
||||||
GetPosition() d2vector.Position
|
GetPosition() d2vector.Position
|
||||||
GetVelocity() d2vector.Vector
|
GetVelocity() d2vector.Vector
|
||||||
|
GetSize() (width, height int)
|
||||||
GetLayer() int
|
GetLayer() int
|
||||||
GetPositionF() (float64, float64)
|
GetPositionF() (float64, float64)
|
||||||
Name() string
|
Name() string
|
||||||
|
@ -20,6 +20,12 @@ type Composite struct {
|
|||||||
direction int
|
direction int
|
||||||
equipment [d2enum.CompositeTypeMax]string
|
equipment [d2enum.CompositeTypeMax]string
|
||||||
mode *compositeMode
|
mode *compositeMode
|
||||||
|
size *size
|
||||||
|
}
|
||||||
|
|
||||||
|
type size struct {
|
||||||
|
Width int
|
||||||
|
Height int
|
||||||
}
|
}
|
||||||
|
|
||||||
// CreateComposite creates a Composite from a given ObjectLookupRecord and palettePath.
|
// CreateComposite creates a Composite from a given ObjectLookupRecord and palettePath.
|
||||||
@ -300,6 +306,43 @@ func (c *Composite) loadCompositeLayer(layerKey, layerValue, animationMode, weap
|
|||||||
return nil, errors.New("animation not found")
|
return nil, errors.New("animation not found")
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func (c *Composite) GetSize() (w, h int) {
|
||||||
|
c.updateSize()
|
||||||
|
return c.size.Width, c.size.Height
|
||||||
|
}
|
||||||
|
|
||||||
|
func (c *Composite) updateSize() {
|
||||||
|
if c.mode == nil {
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
direction := d2cof.Dir64ToCof(c.direction, c.mode.cof.NumberOfDirections)
|
||||||
|
|
||||||
|
biggestW, biggestH := 0, 0
|
||||||
|
|
||||||
|
for _, layerIndex := range c.mode.cof.Priority[direction][c.mode.frameIndex] {
|
||||||
|
layer := c.mode.layers[layerIndex]
|
||||||
|
if layer != nil {
|
||||||
|
w, h := layer.GetCurrentFrameSize()
|
||||||
|
|
||||||
|
if biggestW < w {
|
||||||
|
biggestW = w
|
||||||
|
}
|
||||||
|
|
||||||
|
if biggestH < h {
|
||||||
|
biggestH = h
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if c.size == nil {
|
||||||
|
c.size = &size{}
|
||||||
|
}
|
||||||
|
|
||||||
|
c.size.Width = biggestW
|
||||||
|
c.size.Height = biggestH
|
||||||
|
}
|
||||||
|
|
||||||
func baseString(baseType d2enum.ObjectType) string {
|
func baseString(baseType d2enum.ObjectType) string {
|
||||||
switch baseType {
|
switch baseType {
|
||||||
case d2enum.ObjectTypePlayer:
|
case d2enum.ObjectTypePlayer:
|
||||||
|
@ -21,16 +21,17 @@ type AnimatedEntity struct {
|
|||||||
// Render draws this animated entity onto the target
|
// Render draws this animated entity onto the target
|
||||||
func (ae *AnimatedEntity) Render(target d2interface.Surface) {
|
func (ae *AnimatedEntity) Render(target d2interface.Surface) {
|
||||||
renderOffset := ae.Position.RenderOffset()
|
renderOffset := ae.Position.RenderOffset()
|
||||||
target.PushTranslation(
|
ox, oy := renderOffset.X(), renderOffset.Y()
|
||||||
int((renderOffset.X()-renderOffset.Y())*16),
|
tx, ty := int((ox-oy)*16), int((ox+oy)*8)-5
|
||||||
int(((renderOffset.X()+renderOffset.Y())*8)-5),
|
|
||||||
)
|
target.PushTranslation(tx, ty)
|
||||||
|
|
||||||
defer target.Pop()
|
defer target.Pop()
|
||||||
|
|
||||||
if ae.highlight {
|
if ae.highlight {
|
||||||
target.PushBrightness(2)
|
target.PushBrightness(2)
|
||||||
defer target.Pop()
|
defer target.Pop()
|
||||||
|
|
||||||
ae.highlight = false
|
ae.highlight = false
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -39,3 +39,18 @@ func (i *Item) Highlight() {
|
|||||||
func (i *Item) Name() string {
|
func (i *Item) Name() string {
|
||||||
return i.Item.Name()
|
return i.Item.Name()
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// GetSize returns the current frame size
|
||||||
|
func (i *Item) GetSize() (width, height int) {
|
||||||
|
w, h := i.animation.GetCurrentFrameSize()
|
||||||
|
|
||||||
|
if w < minHitboxSize {
|
||||||
|
w = minHitboxSize
|
||||||
|
}
|
||||||
|
|
||||||
|
if h < minHitboxSize {
|
||||||
|
h = minHitboxSize
|
||||||
|
}
|
||||||
|
|
||||||
|
return w, h
|
||||||
|
}
|
||||||
|
@ -4,6 +4,10 @@ import (
|
|||||||
"github.com/OpenDiablo2/OpenDiablo2/d2common/d2math/d2vector"
|
"github.com/OpenDiablo2/OpenDiablo2/d2common/d2math/d2vector"
|
||||||
)
|
)
|
||||||
|
|
||||||
|
const (
|
||||||
|
minHitboxSize = 30
|
||||||
|
)
|
||||||
|
|
||||||
// mapEntity represents an entity on the map that can be animated
|
// mapEntity represents an entity on the map that can be animated
|
||||||
type mapEntity struct {
|
type mapEntity struct {
|
||||||
Position d2vector.Position
|
Position d2vector.Position
|
||||||
@ -206,3 +210,8 @@ func (m *mapEntity) Highlight() {
|
|||||||
func (m *mapEntity) Selectable() bool {
|
func (m *mapEntity) Selectable() bool {
|
||||||
return false
|
return false
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// GetSize returns the current frame size
|
||||||
|
func (m *mapEntity) GetSize() (width, height int) {
|
||||||
|
return minHitboxSize, minHitboxSize
|
||||||
|
}
|
||||||
|
@ -175,3 +175,8 @@ func (v *NPC) GetPosition() d2vector.Position {
|
|||||||
func (v *NPC) GetVelocity() d2vector.Vector {
|
func (v *NPC) GetVelocity() d2vector.Vector {
|
||||||
return v.mapEntity.velocity
|
return v.mapEntity.velocity
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// GetSize returns the current frame size
|
||||||
|
func (v* NPC) GetSize() (width, height int) {
|
||||||
|
return v.composite.GetSize()
|
||||||
|
}
|
||||||
|
@ -192,3 +192,12 @@ func (p *Player) GetPosition() d2vector.Position {
|
|||||||
func (p *Player) GetVelocity() d2vector.Vector {
|
func (p *Player) GetVelocity() d2vector.Vector {
|
||||||
return p.mapEntity.velocity
|
return p.mapEntity.velocity
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// GetSize returns the current frame size
|
||||||
|
func (p *Player) GetSize() (width, height int) {
|
||||||
|
width, height = p.composite.GetSize()
|
||||||
|
// hack: we need to get full size of composite animations, currently only gets legs
|
||||||
|
height = (height * 2) - (height / 2)
|
||||||
|
|
||||||
|
return width, height
|
||||||
|
}
|
||||||
|
@ -361,6 +361,41 @@ func (mr *MapRenderer) renderEntityDebug(target d2interface.Surface) {
|
|||||||
|
|
||||||
offX, offY := 40, -40
|
offX, offY := 40, -40
|
||||||
|
|
||||||
|
entScreenXf, entScreenYf := mr.WorldToScreenF(e.GetPositionF())
|
||||||
|
entScreenX := int(math.Floor(entScreenXf))
|
||||||
|
entScreenY := int(math.Floor(entScreenYf))
|
||||||
|
entityWidth, entityHeight := e.GetSize()
|
||||||
|
halfWidth, halfHeight := entityWidth/2, entityHeight/2
|
||||||
|
l, r := entScreenX-halfWidth, entScreenX+halfWidth
|
||||||
|
t, b := entScreenY-halfHeight, entScreenY+halfHeight
|
||||||
|
mx, my := mr.renderer.GetCursorPos()
|
||||||
|
xWithin := (l <= mx) && (r >= mx)
|
||||||
|
yWithin := (t <= my) && (b >= my)
|
||||||
|
within := xWithin && yWithin
|
||||||
|
|
||||||
|
boxLineColor := color.RGBA{255, 0, 255, 128}
|
||||||
|
boxHoverColor := color.RGBA{255, 255, 0, 128}
|
||||||
|
|
||||||
|
boxColor := boxLineColor
|
||||||
|
|
||||||
|
if within {
|
||||||
|
boxColor = boxHoverColor
|
||||||
|
}
|
||||||
|
|
||||||
|
// box
|
||||||
|
mr.viewport.PushTranslationWorld(x, y)
|
||||||
|
target.PushTranslation(screenX, screenY)
|
||||||
|
target.PushTranslation(-halfWidth, -halfHeight)
|
||||||
|
target.DrawLine(0, entityHeight, boxColor)
|
||||||
|
target.DrawLine(entityWidth, 0, boxColor)
|
||||||
|
target.PushTranslation(entityWidth, entityHeight)
|
||||||
|
target.DrawLine(-entityWidth, 0, boxColor)
|
||||||
|
target.DrawLine(0, -entityHeight, boxColor)
|
||||||
|
target.PopN(3)
|
||||||
|
mr.viewport.PopTranslation()
|
||||||
|
|
||||||
|
// hover
|
||||||
|
if within {
|
||||||
mr.viewport.PushTranslationWorld(x, y)
|
mr.viewport.PushTranslationWorld(x, y)
|
||||||
target.PushTranslation(screenX, screenY)
|
target.PushTranslation(screenX, screenY)
|
||||||
target.DrawLine(offX, offY, color.RGBA{255, 255, 255, 128})
|
target.DrawLine(offX, offY, color.RGBA{255, 255, 255, 128})
|
||||||
@ -374,6 +409,7 @@ func (mr *MapRenderer) renderEntityDebug(target d2interface.Surface) {
|
|||||||
target.Pop()
|
target.Pop()
|
||||||
mr.viewport.PopTranslation()
|
mr.viewport.PopTranslation()
|
||||||
}
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// WorldToScreen returns the screen (pixel) position for the given isometric world position as two ints.
|
// WorldToScreen returns the screen (pixel) position for the given isometric world position as two ints.
|
||||||
|
@ -142,3 +142,8 @@ func (ob *Object) GetPosition() d2vector.Position {
|
|||||||
func (ob *Object) GetVelocity() d2vector.Vector {
|
func (ob *Object) GetVelocity() d2vector.Vector {
|
||||||
return *d2vector.VectorZero()
|
return *d2vector.VectorZero()
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// GetSize returns the current frame size
|
||||||
|
func (ob *Object) GetSize() (width, height int) {
|
||||||
|
return ob.composite.GetSize()
|
||||||
|
}
|
||||||
|
@ -110,6 +110,26 @@ func (v *Game) OnLoad(_ d2screen.LoadingState) {
|
|||||||
v.debugSpawnItemAtLocation(x, y, codes...)
|
v.debugSpawnItemAtLocation(x, y, codes...)
|
||||||
},
|
},
|
||||||
)
|
)
|
||||||
|
|
||||||
|
v.terminal.BindAction(
|
||||||
|
"spawnmon",
|
||||||
|
"spawn monster at the local player position",
|
||||||
|
func(name string) {
|
||||||
|
x := int(v.localPlayer.Position.X())
|
||||||
|
y := int(v.localPlayer.Position.Y())
|
||||||
|
monstat := d2datadict.MonStats[name]
|
||||||
|
if monstat == nil {
|
||||||
|
v.terminal.OutputErrorf("no monstat entry for \"%s\"", name)
|
||||||
|
return
|
||||||
|
}
|
||||||
|
monster, err := d2mapentity.NewNPC(x, y, monstat, 0)
|
||||||
|
if err != nil {
|
||||||
|
v.terminal.OutputErrorf("error generating monster \"%s\": %v", name, err)
|
||||||
|
return
|
||||||
|
}
|
||||||
|
v.gameClient.MapEngine.AddEntity(monster)
|
||||||
|
},
|
||||||
|
)
|
||||||
}
|
}
|
||||||
|
|
||||||
// OnUnload releases the resources of Gameplay screen
|
// OnUnload releases the resources of Gameplay screen
|
||||||
|
@ -37,6 +37,7 @@ const (
|
|||||||
staminaBarWidth = 102.0
|
staminaBarWidth = 102.0
|
||||||
globeHeight = 80
|
globeHeight = 80
|
||||||
globeWidth = 80
|
globeWidth = 80
|
||||||
|
hoverLabelOuterPad = 5
|
||||||
)
|
)
|
||||||
|
|
||||||
// GameControls represents the game's controls on the screen
|
// GameControls represents the game's controls on the screen
|
||||||
@ -423,14 +424,25 @@ func (g *GameControls) Render(target d2interface.Surface) error {
|
|||||||
continue
|
continue
|
||||||
}
|
}
|
||||||
|
|
||||||
|
entPos := entity.GetPosition()
|
||||||
|
entOffset := entPos.RenderOffset()
|
||||||
entScreenXf, entScreenYf := g.mapRenderer.WorldToScreenF(entity.GetPositionF())
|
entScreenXf, entScreenYf := g.mapRenderer.WorldToScreenF(entity.GetPositionF())
|
||||||
entScreenX := int(math.Floor(entScreenXf))
|
entScreenX := int(math.Floor(entScreenXf))
|
||||||
entScreenY := int(math.Floor(entScreenYf))
|
entScreenY := int(math.Floor(entScreenYf))
|
||||||
|
entityWidth, entityHeight := entity.GetSize()
|
||||||
|
halfWidth, halfHeight := entityWidth/2, entityHeight/2
|
||||||
|
l, r := entScreenX-halfWidth-hoverLabelOuterPad, entScreenX+halfWidth+hoverLabelOuterPad
|
||||||
|
t, b := entScreenY-halfHeight-hoverLabelOuterPad, entScreenY+halfHeight-hoverLabelOuterPad
|
||||||
|
mx, my := g.lastMouseX, g.lastMouseY
|
||||||
|
xWithin := (l <= mx) && (r >= mx)
|
||||||
|
yWithin := (t <= my) && (b >= my)
|
||||||
|
within := xWithin && yWithin
|
||||||
|
|
||||||
if ((entScreenX - 20) <= g.lastMouseX) && ((entScreenX + 20) >= g.lastMouseX) &&
|
if within {
|
||||||
((entScreenY - 80) <= g.lastMouseY) && (entScreenY >= g.lastMouseY) {
|
xOff, yOff := int(entOffset.X()), int(entOffset.Y())
|
||||||
g.nameLabel.SetText(entity.Name())
|
g.nameLabel.SetText(entity.Name())
|
||||||
g.nameLabel.SetPosition(entScreenX, entScreenY-100)
|
xLabel, yLabel := entScreenX-xOff, entScreenY-yOff-entityHeight-hoverLabelOuterPad
|
||||||
|
g.nameLabel.SetPosition(xLabel, yLabel)
|
||||||
g.nameLabel.Render(target)
|
g.nameLabel.Render(target)
|
||||||
entity.Highlight()
|
entity.Highlight()
|
||||||
|
|
||||||
|
Loading…
Reference in New Issue
Block a user