我现在有一个基于服务器客户端通信的游戏。我的问题是,现在使用我的代码,当玩家向服务器发送消息并且服务器更新宇宙/世界时,它会创建一个包并将整个宇宙/世界发送给玩家。由于服务器必须更新的大量数据,制作一个捆绑包,然后将其发送给玩家,如果更多的玩家决定加入,则会造成延迟或减慢游戏速度。从在线阅读内容,我知道玩家和服务器必须拥有几乎相同的宇宙副本,并且服务器只需向其他玩家发送的内容就是世界上正在改变的东西,玩家自己的世界/宇宙将更新游戏。我也知道必须改变的是我的协议。这是我到目前为止我的服务器和客户端协议。
播放器:
; Marshalling and unmarshalling
; shot --> message
(define (marsh-shot s)
(list 'new-shot (posn-x s) (posn-y s)))
; string --> message
(define (marsh-rocket-move direction)
(list 'rocket-move direction))
; message --> world
(define (unmarsh-world mess)
(make-world (map (lambda (xn) (make-ar (first xn) (first (rest xn))))
(second mess))
(map (lambda (xy) (make-posn (first xy) (first (rest xy))))
(third mess))
(fourth mess)
(map (lambda (xy) (make-posn (first xy) (first (rest xy))))
(fifth mess))
(sixth mess)))
; message --> ar
(define (unmarsh-rckt-mv m)
(make-ar (first (rest m))
(first (rest (rest m)))))
; message --> shot
(define (unmarsh-shot m)
(make-posn (first (rest m))
(first (rest (rest m)))))
; mess --> string
(define (unmarsh-rm-ally mess)
(second mess))
; mess --> ar
(define (unmarsh-new-ally mess)
(make-ar (second mess)
(third mess)))
; mess --> loa
(define (unmarsh-loa mess)
(map (lambda (xy) (make-posn (first xy) (second xy)))
(rest mess)))
; key processing
; loar --> number
(define (get-my-x l)
(cond [(empty? l) (error "Could not find my x in the loar")]
[(string=? (ar-name (first l)) MY-ID) (ar-x (first l))]
[else (get-my-x (rest l))]))
; process-key: world key --> package or world
; Purpose: This function is the handler to process key events.
(define (process-key a-world key)
; prior or up
(cond [(key=? "up" key)
(make-package
a-world
(marsh-shot (make-posn (get-my-x (world-allies a-world)) ROCKET-Y)))]
[(or (key=? "right" key) (key=? "left" key))
(make-package
a-world
(marsh-rocket-move key))]
[else a-world]))
; process-message: world message --> world
(define (process-message w mess)
(cond [(symbol=? 'world (first mess))
(unmarsh-world mess)]
[else (error "World received an unknown message" mess)]))
; world --> boolean
(define (game-over? w) (world-over w))
(big-bang INIT-WORLD
(on-draw draw-world)
(on-key process-key)
(on-receive process-message)
(register LOCALHOST)
(name MY-ID)
(stop-when game-over?))
服务器:
; Marshalling
; world string --> message
(define (marsh-world w)
(list
'world
(map (lambda (a) (list (ar-x a) (ar-name a))) (world-allies w))
(map (lambda (a) (list (posn-x a) (posn-y a))) (world-aliens w))
(world-dir w)
(map (lambda (s) (list (posn-x s) (posn-y s))) (world-shots w))
(world-over w)))
; message --> string
(define (unmarsh-rocket-move m) (second m))
; message --> shot
(define (unmarsh-shot m)
(make-posn (second m)
(third m)))
; ar --> message
(define (marsh-rckt-mv an-ar)
(list 'rocket-move (ar-x an-ar) (ar-name an-ar)))
; loa --> message
(define (marsh-loa a-loa)
(cons 'init-army
(map (lambda (a) (list (posn-x a) (posn-y a)))
a-loa)))
; Universe handlers
; add-new-world: univ iworld --> bundle
(define (add-new-world u w)
(cond [(empty? (univ-worlds u))
(local [(define new-worlds (list w))
(define new-state (make-world (list (make-ar (/ WIDTH 2) (iworld-name w)))
INIT-LOA
"left"
INIT-LOS
false))]
(make-bundle
(make-univ new-worlds new-state)
(list (make-mail w (marsh-world new-state)))
empty))]
[else
(local [(define new-worlds (cons w (univ-worlds u)))
(define new-state (make-world (cons (make-ar (/ WIDTH 2) (iworld-name w))
(world-allies (univ-state u)))
(world-aliens (univ-state u))
(world-dir (univ-state u))
(world-shots (univ-state u))
false))]
(make-bundle
(make-univ new-worlds new-state)
(map (lambda (iw) (make-mail iw (marsh-world new-state))) new-worlds)
empty))]))
; rm-world: symbol (listof iworld) --> univ
(define (rm-world name u)
(cond [(empty? u) (error "World to remove for mail list not found")]
[(string=? name (iworld-name (first u))) (rest u)]
[else (cons (first u) (rm-world name (rest u)))]))
; rm-ally: name (listof ar) --> (listof ar)
(define (rm-ally nm l)
(cond [(empty? l) (error "Ally to remove not found!")]
[(string=? nm (ar-name (first l))) (rest l)]
[else (cons (first l) (rm-ally nm (rest l)))]))
; rm-this-world: univ iworld --> bundle
(define (rm-this-world u iw)
(local [(define new-worlds (rm-world (iworld-name iw) (univ-worlds u)))
(define new-state (make-world (rm-ally (iworld-name iw)
(world-allies (univ-state u)))
(world-aliens (univ-state u))
(world-dir (univ-state u))
(world-shots (univ-state u))
(world-over (univ-state u))))]
(make-bundle (make-univ new-worlds new-state)
(map (lambda (iw) (make-mail iw (marsh-world new-state))) new-worlds)
empty)))
; shot los --> los
(define (update-shots s l) (cons s l))
; receive-message: univ iworld --> bundle
(define (receive-message u w msg)
(cond [(symbol=? (first msg) 'rocket-move)
(local [(define new-state (make-world (move-ally (world-allies (univ-state u))
(iworld-name w)
(unmarsh-rocket-move msg))
(world-aliens (univ-state u))
(world-dir (univ-state u))
(world-shots (univ-state u))
(world-over (univ-state u))))]
(make-bundle (make-univ (univ-worlds u) new-state)
(map (lambda (iw) (make-mail iw (marsh-world new-state)))
(univ-worlds u))
empty))]
[(symbol=? (first msg) 'new-shot)
(local [(define new-state (make-world (world-allies (univ-state u))
(world-aliens (univ-state u))
(world-dir (univ-state u))
(update-shots (unmarsh-shot msg)
(world-shots (univ-state u)))
(world-over (univ-state u))))]
(make-bundle (make-univ (univ-worlds u) new-state)
(map (lambda (iw) (make-mail iw (marsh-world new-state)))
(univ-worlds u))
empty))]
[else (error "Unknown message type sent to the server")]))
; world --> world
(define (game-over-world w)
(make-world (world-allies w)
(world-aliens w)
(world-dir w)
(world-shots w)
true))
; univ --> univ
(define (update-univ u)
(cond [(game-over? (univ-state u))
(make-bundle u
(map (lambda (iw)
(make-mail iw (marsh-world (game-over-world (univ-state u)))))
(univ-worlds u))
empty)]
[else
(local [(define new-world (update-world (univ-state u)))]
(make-bundle
(make-univ (univ-worlds u) new-world)
(map (lambda (iw) (make-mail iw (marsh-world new-world))) (univ-worlds u))
empty))]))
(universe initU
(on-new add-new-world)
(on-msg receive-message)
(on-disconnect rm-this-world)
(on-tick update-univ)
)