mirror of
https://github.com/OpenDiablo2/OpenDiablo2
synced 2024-12-26 12:06:24 -05:00
Get and use draw order and animation speed for objects (#473)
* String2enum ObjectAnimationMode * Render objects at their assigned layer Gets the orderflag from the object record and assign it to the mapentity so the renderer can get at it. This adds another render pass that loops through the objects. * Get object animation speed from their txt entry
This commit is contained in:
parent
66e6d32680
commit
11f743aa42
@ -58,3 +58,4 @@ const (
|
||||
//go:generate stringer -linecomment -type PlayerAnimationMode
|
||||
//go:generate stringer -linecomment -type MonsterAnimationMode
|
||||
//go:generate stringer -linecomment -type ObjectAnimationMode
|
||||
//go:generate string2enum -samepkg -linecomment -type ObjectAnimationMode
|
||||
|
40
d2common/d2enum/objectanimationmode_string2enum.go
Normal file
40
d2common/d2enum/objectanimationmode_string2enum.go
Normal file
@ -0,0 +1,40 @@
|
||||
// Code generated by "string2enum -samepkg -linecomment -type ObjectAnimationMode"; DO NOT EDIT.
|
||||
|
||||
package d2enum
|
||||
|
||||
import "fmt"
|
||||
|
||||
// ObjectAnimationModeFromString returns the ObjectAnimationMode enum corresponding to s.
|
||||
func ObjectAnimationModeFromString(s string) ObjectAnimationMode {
|
||||
if len(s) == 0 {
|
||||
return 0
|
||||
}
|
||||
for i := range _ObjectAnimationMode_index[:len(_ObjectAnimationMode_index)-1] {
|
||||
if s == _ObjectAnimationMode_name[_ObjectAnimationMode_index[i]:_ObjectAnimationMode_index[i+1]] {
|
||||
return ObjectAnimationMode(i)
|
||||
}
|
||||
}
|
||||
panic(fmt.Errorf("unable to locate ObjectAnimationMode enum corresponding to %q", s))
|
||||
}
|
||||
|
||||
func _(s string) {
|
||||
// Check for duplicate string values in type "ObjectAnimationMode".
|
||||
switch s {
|
||||
// 0
|
||||
case "NU":
|
||||
// 1
|
||||
case "OP":
|
||||
// 2
|
||||
case "ON":
|
||||
// 3
|
||||
case "S1":
|
||||
// 4
|
||||
case "S2":
|
||||
// 5
|
||||
case "S3":
|
||||
// 6
|
||||
case "S4":
|
||||
// 7
|
||||
case "S5":
|
||||
}
|
||||
}
|
@ -81,6 +81,16 @@ func (c *Composite) SetMode(animationMode, weaponClass string, direction int) er
|
||||
return nil
|
||||
}
|
||||
|
||||
func (c *Composite) SetSpeed(speed int) {
|
||||
c.mode.animationSpeed = 1.0 / ((float64(speed) * 25.0) / 256.0)
|
||||
for layerIdx := range c.mode.layers {
|
||||
layer := c.mode.layers[layerIdx]
|
||||
if layer != nil {
|
||||
layer.SetPlaySpeed(c.mode.animationSpeed)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
func (c *Composite) GetDirectionCount() int {
|
||||
if c.mode == nil {
|
||||
return 0
|
||||
|
@ -12,6 +12,7 @@ type MapEntity interface {
|
||||
Render(target d2render.Surface)
|
||||
Advance(tickTime float64)
|
||||
GetPosition() (float64, float64)
|
||||
GetLayer() (int)
|
||||
GetPositionF() (float64, float64)
|
||||
Name() string
|
||||
}
|
||||
@ -28,6 +29,7 @@ type mapEntity struct {
|
||||
TargetY float64
|
||||
Speed float64
|
||||
path []d2astar.Pather
|
||||
drawLayer int
|
||||
|
||||
done func()
|
||||
directioner func(direction int)
|
||||
@ -46,10 +48,15 @@ func createMapEntity(x, y int) mapEntity {
|
||||
subcellX: 1 + math.Mod(locX, 5),
|
||||
subcellY: 1 + math.Mod(locY, 5),
|
||||
Speed: 6,
|
||||
drawLayer: 0,
|
||||
path: []d2astar.Pather{},
|
||||
}
|
||||
}
|
||||
|
||||
func (m *mapEntity) GetLayer() int {
|
||||
return m.drawLayer
|
||||
}
|
||||
|
||||
func (m *mapEntity) SetPath(path []d2astar.Pather, done func()) {
|
||||
m.path = path
|
||||
m.done = done
|
||||
|
@ -1,6 +1,7 @@
|
||||
package d2mapentity
|
||||
|
||||
import (
|
||||
"github.com/OpenDiablo2/OpenDiablo2/d2common/d2enum"
|
||||
"github.com/OpenDiablo2/OpenDiablo2/d2common/d2data/d2datadict"
|
||||
"github.com/OpenDiablo2/OpenDiablo2/d2core/d2asset"
|
||||
"github.com/OpenDiablo2/OpenDiablo2/d2core/d2render"
|
||||
@ -29,6 +30,7 @@ func CreateObject(x, y int, object *d2datadict.ObjectLookupRecord, palettePath s
|
||||
}
|
||||
entity.mapEntity.directioner = entity.rotate
|
||||
entity.objectRecord = d2datadict.Objects[object.ObjectsTxtId]
|
||||
entity.drawLayer = entity.objectRecord.OrderFlag[d2enum.AnimationModeObjectNeutral]
|
||||
return entity, nil
|
||||
}
|
||||
|
||||
@ -43,7 +45,9 @@ func (ob *Object) SetMode(animationMode, weaponClass string, direction int) erro
|
||||
err = ob.composite.SetMode(animationMode, "HTH", direction)
|
||||
ob.weaponClass = "HTH"
|
||||
}
|
||||
|
||||
ob.mapEntity.drawLayer = ob.objectRecord.OrderFlag[d2enum.ObjectAnimationModeFromString(animationMode)]
|
||||
// For objects their txt record entry overrides animationdata
|
||||
ob.composite.SetSpeed(ob.objectRecord.FrameDelta[d2enum.ObjectAnimationModeFromString(animationMode)])
|
||||
return err
|
||||
}
|
||||
|
||||
|
@ -71,8 +71,8 @@ func (mr *MapRenderer) Render(target d2render.Surface) {
|
||||
if mr.debugVisLevel > 0 {
|
||||
mr.renderDebug(mr.debugVisLevel, target, startX, startY, endX, endY)
|
||||
}
|
||||
mr.renderPass2(target, startX, startY, endX, endY)
|
||||
mr.renderPass3(target, startX, startY, endX, endY)
|
||||
mr.renderPass4(target, startX, startY, endX, endY)
|
||||
}
|
||||
|
||||
func (mr *MapRenderer) MoveCameraTo(x, y float64) {
|
||||
@ -95,6 +95,7 @@ func (mr *MapRenderer) WorldToOrtho(x, y float64) (float64, float64) {
|
||||
return mr.viewport.WorldToOrtho(x, y)
|
||||
}
|
||||
|
||||
// Lower wall tiles, tile shadews, floor tiles
|
||||
func (mr *MapRenderer) renderPass1(target d2render.Surface, startX, startY, endX, endY int) {
|
||||
for tileY := startY; tileY < endY; tileY++ {
|
||||
for tileX := startX; tileX < endX; tileX++ {
|
||||
@ -106,7 +107,32 @@ func (mr *MapRenderer) renderPass1(target d2render.Surface, startX, startY, endX
|
||||
}
|
||||
}
|
||||
|
||||
// Objects below walls
|
||||
func (mr *MapRenderer) renderPass2(target d2render.Surface, startX, startY, endX, endY int) {
|
||||
for tileY := startY; tileY < endY; tileY++ {
|
||||
for tileX := startX; tileX < endX; tileX++ {
|
||||
mr.viewport.PushTranslationWorld(float64(tileX), float64(tileY))
|
||||
|
||||
// TODO: Do not loop over every entity every frame
|
||||
for _, mapEntity := range *mr.mapEngine.Entities() {
|
||||
entityX, entityY := mapEntity.GetPosition()
|
||||
if (int(entityX) != tileX) || (int(entityY) != tileY) {
|
||||
continue
|
||||
}
|
||||
if mapEntity.GetLayer() != 1 {
|
||||
continue
|
||||
}
|
||||
target.PushTranslation(mr.viewport.GetTranslationScreen())
|
||||
mapEntity.Render(target)
|
||||
target.Pop()
|
||||
}
|
||||
mr.viewport.PopTranslation()
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// Upper wall tiles, objects that are on top of walls
|
||||
func (mr *MapRenderer) renderPass3(target d2render.Surface, startX, startY, endX, endY int) {
|
||||
for tileY := startY; tileY < endY; tileY++ {
|
||||
for tileX := startX; tileX < endX; tileX++ {
|
||||
tile := mr.mapEngine.TileAt(tileX, tileY)
|
||||
@ -119,6 +145,9 @@ func (mr *MapRenderer) renderPass2(target d2render.Surface, startX, startY, endX
|
||||
if (int(entityX) != tileX) || (int(entityY) != tileY) {
|
||||
continue
|
||||
}
|
||||
if mapEntity.GetLayer() == 1 {
|
||||
continue
|
||||
}
|
||||
target.PushTranslation(mr.viewport.GetTranslationScreen())
|
||||
mapEntity.Render(target)
|
||||
target.Pop()
|
||||
@ -128,7 +157,8 @@ func (mr *MapRenderer) renderPass2(target d2render.Surface, startX, startY, endX
|
||||
}
|
||||
}
|
||||
|
||||
func (mr *MapRenderer) renderPass3(target d2render.Surface, startX, startY, endX, endY int) {
|
||||
// Roof tiles
|
||||
func (mr *MapRenderer) renderPass4(target d2render.Surface, startX, startY, endX, endY int) {
|
||||
for tileY := startY; tileY < endY; tileY++ {
|
||||
for tileX := startX; tileX < endX; tileX++ {
|
||||
tile := mr.mapEngine.TileAt(tileX, tileY)
|
||||
|
Loading…
Reference in New Issue
Block a user