ABOUT ME

-

  • 서버-클라이언트 연결
    Programming/DirectX12 2022. 3. 30. 00:39

    Graduation Project

    졸업작품 게임은 3인이서 플레이하는 게임이다.

    우선 서버-클라이언트 네트워크 관련 틀을 잡기 위해 플레이어 이동만 구현해보도록 했다.

     

     

     

     

    void GameFramework::OnInit(HINSTANCE hInstance, HWND hWnd)
    {
    	m_hInstance = hInstance;
    	m_hWnd = hWnd;
    
    	LoadPipeline();
    	LoadAssets();
    
    #ifdef NETWORK
    	ConnectServer();
    	m_networkThread = thread{ &GameFramework::ProcessClient, this, reinterpret_cast<LPVOID>(g_c_socket) };
    #endif
    }
    void Scene::ProcessClient(LPVOID arg)
    {
    	while (g_isConnected)
    		RecvPacket();
    }

    클라이언트를 켤 때 네트워크 쓰레드를 만들어서 서버와 통신한다.

     

     

     

     

     

    void Scene::RecvPacket()
    {
    	// 생략...
        switch (recv_buf[1])
    	{
    	// 생략...
    	case SC_PACKET_UPDATE_CLIENT:
    	{
    		sc_packet_update_client packet;
    		memcpy(reinterpret_cast<char*>(&packet), recv_buf, sizeof(recv_buf));
    
    		// 나에 대한 정보는 무시
    		if (m_player->GetId() == packet.data.id)
    			break;
    
    		for (auto& p : m_multiPlayers)
    		{
    			if (!p) continue;
    			//if (p->GetId() != packet.data.id) continue;
    			if (AnimationInfo* aniInfo{ p->GetAnimationInfo() })
    			{
    				switch (packet.data.state)
    				{
    				case eLegState::IDLE:
    					if (p->GetCurrAnimationName() != "IDLE" && p->GetAfterAnimationName() != "IDLE")
    						p->PlayAnimation("IDLE", TRUE);
    					break;
    				case eLegState::WALKING:
    					if (p->GetCurrAnimationName() != "WALKING" && p->GetAfterAnimationName() != "WALKING")
    						p->PlayAnimation("WALKING", TRUE);
    					break;
    				case eLegState::WALKLEFT:
    					if (p->GetCurrAnimationName() != "WALKLEFT" && p->GetAfterAnimationName() != "WALKLEFT")
    						p->PlayAnimation("WALKLEFT", TRUE);
    					break;
    				case eLegState::WALKRIGHT:
    					if (p->GetCurrAnimationName() != "WALKRIGHT" && p->GetAfterAnimationName() != "WALKRIGHT")
    						p->PlayAnimation("WALKRIGHT", TRUE);
    					break;
    				case eLegState::WALKBACK:
    					if (p->GetCurrAnimationName() != "WALKBACK" && p->GetAfterAnimationName() != "WALKBACK")
    						p->PlayAnimation("WALKBACK", TRUE);
    					break;
    				case eLegState::RUNNING:
    					if (p->GetCurrAnimationName() != "RUNNING" && p->GetAfterAnimationName() != "RUNNING")
    						p->PlayAnimation("RUNNING", TRUE);
    					break;
    				}
    			}
    			p->SetPosition(packet.data.pos);
    			p->SetVelocity(packet.data.velocity);
    			FLOAT yaw{ p->GetRollPitchYaw().z };
    			p->Rotate(0.0f, 0.0f, packet.data.yaw - yaw);
    		}
    		break;
    	}
    	// 생략...
    	}
    }

    서버로부터 'SC_PACKET_UPDATE_CLIENT' 패킷을 받으면 해당 멀티플레이어의 정보를 최신화 해준다.

    멀티플레이어의 애니메이션, 위치, 속도, 회전각을 설정해준다.

     

     

     

     

     

     

    빨강 : 클라이언트, 파랑 : 서버

    만약 속도없이 멀티플레이어의 위치만 받아서 갱신해주게 된다면 위의 그림처럼 된다.

    원래는 0 ~ 60FPS까지 부드럽게 이동해야겠지만, 30FPS으로 서버가 클라이언트로 데이터를 보내준다면

    멀티플레이어은 30FPS로 움직이는 것처럼 보여지게된다.

     

    따라서 속도도 보내줘서 파랑 점 사이의 구간은 전달받은 속도로 움직이게 한다.

    그렇게 되면 서버가 몇 FPS로 보내는지에 상관없이 부드럽게 움직인다.

    다만 서버가 보내지는 FPS가 낮아지면 그 사이 움직임이 그만큼 부정확해진다.

     

     

     

     

     

    움직이면서 화면을 돌리는 중

    위의 움짤로는 잘 모르겠지만 실제 인게임 화면에선 회전할 때 조금 끊기는 느낌이 든다.

    회전도 이동처럼 부드럽게 할 수 있는지는 잘 모르겠다.

    댓글