computing frame deltas

master
Jordan Orelli 4 years ago
parent a470e30a41
commit f512df73dd

@ -56,6 +56,7 @@ func (d *door) exec(w *world, r *room, p *player, seq int) result {
p.Error("failed to add player avatar to tile %v", t)
}
dest.addPlayer(p)
p.fullSync = true
return result{}
}

@ -13,12 +13,12 @@ import (
type player struct {
*blammo.Log
//*room
name string
outbox chan wire.Response
pending *Request
avatar *entity
stop chan bool
name string
outbox chan wire.Response
pending *Request
avatar *entity
stop chan bool
fullSync bool
}
func (p *player) start(c chan Request, conn *websocket.Conn, r *room) {
@ -167,6 +167,7 @@ func (p *player) update(dt time.Duration) {}
type spawnPlayer struct{}
func (s spawnPlayer) exec(w *world, r *room, p *player, seq int) result {
p.fullSync = true
e := entity{
ID: <-w.nextID,
Glyph: '@',

@ -10,8 +10,9 @@ type room struct {
*blammo.Log
name string
math.Rect
tiles []tile
players map[string]*player
tiles []tile
players map[string]*player
lastFrame wire.Frame
}
func (r *room) allEntities() map[int]wire.Entity {

@ -284,6 +284,12 @@ func (w *world) tick(d time.Duration) {
Players: r.playerAvatars(),
}
delta := r.lastFrame.Diff(frame)
if delta != nil {
w.Info("%s delta: %s", r.name, delta)
}
r.lastFrame = frame
for _, p := range r.players {
p.send(wire.Response{Body: frame})
}

@ -1,6 +1,13 @@
package wire
import "github.com/jordanorelli/astro-domu/internal/math"
import (
"bytes"
"fmt"
"strconv"
"strings"
"github.com/jordanorelli/astro-domu/internal/math"
)
type Frame struct {
RoomName string `json:"room_name"`
@ -11,6 +18,141 @@ type Frame struct {
func (Frame) NetTag() string { return "frame" }
func (f Frame) Diff(next Frame) *Delta {
var delta Delta
if f.RoomSize != next.RoomSize {
rs := next.RoomSize
delta.RoomSize = &rs
}
for id, e := range next.Entities {
if old, ok := f.Entities[id]; !ok {
// a new entity
delta.addEntity(e)
} else {
// an existing entity
if e != old {
delta.addEntity(e)
}
}
}
for id, _ := range f.Entities {
// entity removed
if _, ok := next.Entities[id]; !ok {
delta.nullEntity(id)
}
}
for name, id := range next.Players {
if oldID, ok := f.Players[name]; !ok {
// a new player
delta.addPlayer(name, id)
} else {
// an existing player
if oldID != id {
delta.addPlayer(name, id)
}
}
}
for name, _ := range f.Players {
if _, ok := next.Players[name]; !ok {
delta.nullPlayer(name)
}
}
if !delta.IsEmpty() {
return &delta
}
return nil
}
type Delta struct {
RoomSize *math.Rect `json:"room_size,omitempty"`
Entities map[int]*Entity `json:"entities,omitempty"`
Players map[string]*int `json:"players,omitempty"`
}
func (d Delta) String() string {
first := true
var buf bytes.Buffer
fmt.Fprint(&buf, "Δ{")
if d.RoomSize != nil {
fmt.Fprintf(&buf, "size(%d,%d@%d,%d)", d.RoomSize.Origin.X, d.RoomSize.Origin.Y, d.RoomSize.Width, d.RoomSize.Height)
first = false
}
if len(d.Entities) > 0 {
if !first {
buf.WriteString(",")
}
buf.WriteString("entities<")
parts := make([]string, 0, len(d.Entities))
for id, e := range d.Entities {
if e == nil {
parts = append(parts, fmt.Sprintf("-%d", id))
} else {
parts = append(parts, strconv.Itoa(id))
}
}
buf.WriteString(strings.Join(parts, ","))
buf.WriteString(">")
first = false
}
if len(d.Players) > 0 {
if !first {
buf.WriteString(",")
}
buf.WriteString("players<")
parts := make([]string, 0, len(d.Players))
for name, id := range d.Players {
if id == nil {
parts = append(parts, fmt.Sprintf("-%s", name))
} else {
parts = append(parts, fmt.Sprintf("+%s", name))
}
}
buf.WriteString(strings.Join(parts, ","))
buf.WriteString(">")
first = false
}
return buf.String()
}
func (Delta) NetTag() string { return "delta" }
func (d *Delta) addEntity(e Entity) {
if d.Entities == nil {
d.Entities = make(map[int]*Entity)
}
d.Entities[e.ID] = &e
}
func (d *Delta) nullEntity(id int) {
if d.Entities == nil {
d.Entities = make(map[int]*Entity)
}
d.Entities[id] = nil
}
func (d *Delta) addPlayer(name string, id int) {
if d.Players == nil {
d.Players = make(map[string]*int)
}
d.Players[name] = &id
}
func (d *Delta) nullPlayer(name string) {
if d.Players == nil {
d.Players = make(map[string]*int)
}
d.Players[name] = nil
}
func (d Delta) IsEmpty() bool {
return d.RoomSize == nil && len(d.Entities) == 0 && len(d.Players) == 0
}
func init() {
Register(func() Value { return new(Frame) })
}

Loading…
Cancel
Save