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:
Ziemas 2020-06-27 20:30:23 +02:00 committed by GitHub
parent 66e6d32680
commit 11f743aa42
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
6 changed files with 95 additions and 3 deletions

View File

@ -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

View 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":
}
}

View File

@ -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

View File

@ -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

View File

@ -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
}

View File

@ -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)