brunch

You can make anything
by writing

C.S.Lewis

by 앵버박사 May 14. 2016

처음 만드는 온라인 게임 05-03

클라이언트 개발


처음 만드는 온라인 게임 04-02 기억하시나요?


우리는 웹 소켓 서버를 만들었습니다. 하지만 다 채우지 못한 부분이 있었는데, 클라이언트로부터 메시지를 받았을 때 처리되는 비즈니스 로직 부분이었습니다.




class WebsocketServer( ThreadingMixIn, TCPServer ):

    ...

def receive_message( self, handler, message ):

pass




바로 WebsocketServer 클래스의 receive_message 메서드입니다. 이제 receive_message 메서드를 완성하는 것으로 우리의 게임 만들기는 막을 내리게 됩니다.


이전 글에서 클라이언트 로직을 개발했기 때문에 서버에서 어떻게 처리해야 할지 감이 잡히실 겁니다. 기억이 잘 나지 않으신다면 04-02, 05-02 편을 잠깐 다시 보시면 좋을 것 같습니다.


우선 클라이언트에서는 [ Command::JSON 형태의 문자열 파라미터 ] 형식으로 메시지를 전송했습니다. 예로,



"REGISTER::{'roomNo' : 'ROOMNO01'}"

"DATA::{'roomNo' : 'ROOMNO01', 'time' : '24459.555'}"

"UPDATE::{'roomNo' : 'ROOMNO01', 'useId' : 'A1', 'speedV' : 2, 'speedH' : 0, 'left' : 100, 'top' : 100, direction : 'LEFT', 'status' : 'MOVE', 'attackStatus' : 'none'}"



이런 형식으로 메시지가 올 것입니다. 그럼 우리는 서버에서 Command에 따라 분기 처리하는데, register일 때는 새로운 유저를 데이터에 추가하고, data 일 때는 현재 데이터를 유저에게 보내고, update 일 때는 요청한 대로 현재 데이터를 변경해주면 됩니다. 그럼 소스코드를 보겠습니다.




def receive_message( self, handler, message ):

    client = self.find_client( handler )

    oper, data = message.split( '::' )

    data = json.loads( data )


if oper == 'register':

 iflen( self.all_data ) ==2:

            handler.send_message( json.dumps( { 'code' : -1, 'message' : 'Many peoples' } ) )

return

print( 'Register client : ' + str( client[ 'id' ] ) )

        self.all_data[ client[ 'id' ] ] = { 'speedV' : 0, 'speedH' : 0, 'left' : 0, 'top' : 0, 'direction' : 'DOWN', 'status' : 'STAY', 'attackStatus' : 'none', 'energy' : 30 }

        handler.send_message( json.dumps( { 'code' : 0, 'message' : 'success', 'data' : { 'userId' : client[ 'id' ] }, 'status' : 'register' } ) )

elif oper =='data':

        handler.send_message( json.dumps( { 'code' : 0, 'message' : 'success', 'data' : self.all_data, 'time' : data[ 'time' ], 'status' : 'data' } ) )

elif oper == 'update':

        self.all_data[ client[ 'id' ] ][ 'speedV' ] = data[ 'speedV' ]

        self.all_data[ client[ 'id' ] ][ 'speedH' ] = data[ 'speedH' ]

        self.all_data[ client[ 'id' ] ][ 'left' ] = data[ 'left' ]

        self.all_data[ client[ 'id' ] ][ 'top' ] = data[ 'top' ]

        self.all_data[ client[ 'id' ] ][ 'direction' ] = data[ 'direction' ]

        self.all_data[ client[ 'id' ] ][ 'status' ] = data[ 'status' ]

        self.all_data[ client[ 'id' ] ][ 'attackStatus' ] = data[ 'attackStatus' ]


 if data[ 'attackStatus' ] == 'success':

for key in self.all_data.keys():

 if key != client[ 'id' ]:

                    self.all_data[ key ][ 'energy' ] = self.all_data[ key ]['energy' ] -1


        handler.send_message( json.dumps( { 'code' : 0, 'message' : 'success', 'status' : 'update' } ) )




먼저 핸들러를 키로 현재 클라이언트를 가져옵니다. 그리고 메시지 패턴에 따라 :: 로 split 하여 Command와 메시지 본문을 분리합니다.


register 일 때, 이미 유저 2명이 접속해 있으면 오류 메시지를 반환합니다. 참고로 all_data 변수는 아래와 같은 형식입니다.



{
    "USER1" : {
        "speedV" : 0,
        "speedH" : 0,
        "left" : 0,
        "top" : 0,
        "direction" : "DOWN",
        "status" : "STAY",
        "attackStatus" : "none",
        "energy" : 30
    },
    "USER2" : {
        ...
    }
}



이어서 register 커맨드에서는 all_data에 초기값으로 신규 사용자 데이터를 추가한 후, 응답으로 정상 코드와 userId를 전송합니다.


data 커맨드일 경우에는 클라이언트에게 현재의 all_data를 전송해줍니다.


마지막으로 update 커맨드의 경우는 클라이언트로부터 들어온 파라미터로  all_data를 수정하고, attackStatus가 success일 때 상대방의 energy 속성을 1 만큼 감소시킵니다.



이것으로 처음 만드는 온라인 게임 모든 개발이 끝나고 게임을 완성하였습니다. 게임 소스코드 폴더에서 커맨드 창을 2개 띄우고, 각각 HTTP와 WebSocket 두개의 서버를 실행합니다. ( 물론 파이썬3가 설치되어 있어야 합니다. )



python simple_httd.py ( 커맨드 창 1 )

pyhon simple_wsd.py ( 커맨드 창 2 )



그리고 두 대의 PC에서 각각 웹 브라우저를 띄우고, 서버를 띄운 PC의 IP로 접속하게 되면 게임이 실행됩니다.


9편이나 되는 기나긴 글이라 읽는 분들도 쉽지 않았을 것 같습니다. 저도 일일이 다 설명하기에는 분량이 많아 독자분들을 믿고(?) 조금 더 편안하게 글을 작성하기도 했습니다. 그래서 더 이해하기 어렵지 않았을까 염려가 되었습니다. 독자분들의 지식수준이 아닌 제 글 솜씨의 탓입니다.


글을 쓰다가 확실하지 않은 부분은 다시 찾고 정리하다 보니 저 스스로 많은 공부가 되었습니다. 부디 독자 여러분들께도 조금이라도 도움이 되셨기를 바랍니다. 읽어주셔서 고맙습니다.





Contents


01 주제 / 대상 독자 / 개발 원칙

02 요구사항 정의 / 설계

03 Python HTTP Server 개발

  03-01 멀티 쓰레드 지원 / POST 메서드 처리 / 로깅
  03-02 URL 라우팅 / 정적 리소스 처리

04 Python web socket server 개발
  04-01 웹 소켓 개요

  04-02 웹 소켓 서버 구현

05 클라이언트 개발

 05-01 캐릭터 스프라이트 개발

 05-02 클라이언트 로직

 05-03 서버 로직



매거진의 이전글 처음 만드는 온라인 게임 05-02

작품 선택

키워드 선택 0 / 3 0

댓글여부

afliean
브런치는 최신 브라우저에 최적화 되어있습니다. IE chrome safari