mirror of
https://github.com/OpenDiablo2/OpenDiablo2
synced 2025-01-27 03:37:53 -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)
|
||||
GetPosition() d2vector.Position
|
||||
GetVelocity() d2vector.Vector
|
||||
GetSize() (width, height int)
|
||||
GetLayer() int
|
||||
GetPositionF() (float64, float64)
|
||||
Name() string
|
||||
|
@ -20,6 +20,12 @@ type Composite struct {
|
||||
direction int
|
||||
equipment [d2enum.CompositeTypeMax]string
|
||||
mode *compositeMode
|
||||
size *size
|
||||
}
|
||||
|
||||
type size struct {
|
||||
Width int
|
||||
Height int
|
||||
}
|
||||
|
||||
// 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")
|
||||
}
|
||||
|
||||
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 {
|
||||
switch baseType {
|
||||
case d2enum.ObjectTypePlayer:
|
||||
|
@ -21,16 +21,17 @@ type AnimatedEntity struct {
|
||||
// Render draws this animated entity onto the target
|
||||
func (ae *AnimatedEntity) Render(target d2interface.Surface) {
|
||||
renderOffset := ae.Position.RenderOffset()
|
||||
target.PushTranslation(
|
||||
int((renderOffset.X()-renderOffset.Y())*16),
|
||||
int(((renderOffset.X()+renderOffset.Y())*8)-5),
|
||||
)
|
||||
ox, oy := renderOffset.X(), renderOffset.Y()
|
||||
tx, ty := int((ox-oy)*16), int((ox+oy)*8)-5
|
||||
|
||||
target.PushTranslation(tx, ty)
|
||||
|
||||
defer target.Pop()
|
||||
|
||||
if ae.highlight {
|
||||
target.PushBrightness(2)
|
||||
defer target.Pop()
|
||||
|
||||
ae.highlight = false
|
||||
}
|
||||
|
||||
|
@ -39,3 +39,18 @@ func (i *Item) Highlight() {
|
||||
func (i *Item) Name() string {
|
||||
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"
|
||||
)
|
||||
|
||||
const (
|
||||
minHitboxSize = 30
|
||||
)
|
||||
|
||||
// mapEntity represents an entity on the map that can be animated
|
||||
type mapEntity struct {
|
||||
Position d2vector.Position
|
||||
@ -206,3 +210,8 @@ func (m *mapEntity) Highlight() {
|
||||
func (m *mapEntity) Selectable() bool {
|
||||
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 {
|
||||
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 {
|
||||
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,18 +361,54 @@ func (mr *MapRenderer) renderEntityDebug(target d2interface.Surface) {
|
||||
|
||||
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.DrawLine(offX, offY, color.RGBA{255, 255, 255, 128})
|
||||
target.PushTranslation(offX+10, offY-20)
|
||||
target.PushTranslation(-10, -10)
|
||||
target.DrawRect(200, 50, color.RGBA{0, 0, 0, 64})
|
||||
target.Pop()
|
||||
target.DrawTextf("World (%.2f, %.2f)\nVelocity (%.2f, %.2f)", x, y, vx, vy)
|
||||
target.Pop()
|
||||
target.DrawLine(int(vx), int(vy), color.RGBA{64, 255, 0, 255})
|
||||
target.Pop()
|
||||
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)
|
||||
target.PushTranslation(screenX, screenY)
|
||||
target.DrawLine(offX, offY, color.RGBA{255, 255, 255, 128})
|
||||
target.PushTranslation(offX+10, offY-20)
|
||||
target.PushTranslation(-10, -10)
|
||||
target.DrawRect(200, 50, color.RGBA{0, 0, 0, 64})
|
||||
target.Pop()
|
||||
target.DrawTextf("World (%.2f, %.2f)\nVelocity (%.2f, %.2f)", x, y, vx, vy)
|
||||
target.Pop()
|
||||
target.DrawLine(int(vx), int(vy), color.RGBA{64, 255, 0, 255})
|
||||
target.Pop()
|
||||
mr.viewport.PopTranslation()
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -142,3 +142,8 @@ func (ob *Object) GetPosition() d2vector.Position {
|
||||
func (ob *Object) GetVelocity() d2vector.Vector {
|
||||
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.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
|
||||
|
@ -32,11 +32,12 @@ type Panel interface {
|
||||
}
|
||||
|
||||
const (
|
||||
initialMissileID = 59
|
||||
expBarWidth = 120.0
|
||||
staminaBarWidth = 102.0
|
||||
globeHeight = 80
|
||||
globeWidth = 80
|
||||
initialMissileID = 59
|
||||
expBarWidth = 120.0
|
||||
staminaBarWidth = 102.0
|
||||
globeHeight = 80
|
||||
globeWidth = 80
|
||||
hoverLabelOuterPad = 5
|
||||
)
|
||||
|
||||
// GameControls represents the game's controls on the screen
|
||||
@ -423,14 +424,25 @@ func (g *GameControls) Render(target d2interface.Surface) error {
|
||||
continue
|
||||
}
|
||||
|
||||
entPos := entity.GetPosition()
|
||||
entOffset := entPos.RenderOffset()
|
||||
entScreenXf, entScreenYf := g.mapRenderer.WorldToScreenF(entity.GetPositionF())
|
||||
entScreenX := int(math.Floor(entScreenXf))
|
||||
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) &&
|
||||
((entScreenY - 80) <= g.lastMouseY) && (entScreenY >= g.lastMouseY) {
|
||||
if within {
|
||||
xOff, yOff := int(entOffset.X()), int(entOffset.Y())
|
||||
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)
|
||||
entity.Highlight()
|
||||
|
||||
|
Loading…
Reference in New Issue
Block a user