서버가 게임 클라이언트에게 근처에 보이는 다른 플레이어에 대해 효율적인 방법으로 알리도록 하는 방법은 무엇입니까?

StackOverflow https://stackoverflow.com/questions/1623971

문제

저는 멀티플레이어 플래시 게임을 개발 중입니다.서버는 각 클라이언트에게 플레이어 근처에 다른 플레이어가 있는지 알려줍니다.이를 위해 서버는 어떤 클라이언트가 서로 가까이 있는지 지속적으로 확인해야 합니다.다음은 현재 임시 해결책으로 사용하고 있는 것입니다.

private function checkVisibilities()
{
    foreach ($this->socketClients as $socketClient1)
    { //loop every socket client
        if (($socketClient1->loggedIn()) && ($socketClient1->inWorld()))
        { //if this client is logged in and in the world
            foreach ($this->socketClients as $cid2 => $socketClient2)
            { //loop every client for this client to see if they are near
                if ($socketClient1 != $socketClient2)
                { //if it is not the same client
                    if (($socketClient2->loggedIn()) && ($socketClient2->inWorld())
                    { //if this client is also logged in and also in the world
                        if ((abs($socketClient1->getCharX() - $socketClient2->getCharX()) + abs($socketClient1->getCharY() - $socketClient2->getCharY())) < Settings::$visibilities_range)
                        { //the clients are near each other
                            if (!$socketClient1->isVisible($cid2))
             { //not yet visible -> add
                                 $socketClient1->addVisible($cid2);
                            }
                        }
                        else
                        { //the clients are not near each other
                            if ($socketClient1->isVisible($cid2))
                            { //still visible -> remove
                                $socketClient1->removeVisible($cid2);
                            }
                        }
                    }
                    else
                    { //the client is not logged in
                        if ($socketClient1->isVisible($cid2))
                        { //still visible -> remove
                            $socketClient1->removeVisible($cid2);
                        }
                    }       
               }
         }
     }
}

잘 작동합니다.하지만 지금까지 나는 한 번에 2명의 플레이어와만 플레이해 왔습니다.이 기능은 모든 클라이언트에 대해 모든 클라이언트를 반복합니다.따라서 100명의 플레이어가 있는 경우 함수가 실행될 때마다 100 * 100 = 10.000 루프가 됩니다.이것은 최선의 방법이나 가장 효율적인 방법은 아닌 것 같습니다.

이제 여러분은 내 현재 설정에 대해 어떻게 생각하는지, 그리고 이러한 가시성을 처리하는 더 나은 방법에 대한 제안 사항이 있는지 궁금합니다.

업데이트:나는 세상이 무한하다는 것을 언급하는 것을 잊었습니다.그것은 실제로 "우주"입니다.지도가 없습니다.게다가 2차원(2D) 게임이기도 하다.

미리 감사드립니다.

도움이 되었습니까?

해결책

가장 간단한 솔루션은 세계를 균일 한 그리드로 분할하는 것입니다.

_|____|____|____|_
 |    |    |    |
_|____|____|____|_
 |    |    |    |
_|____|____|____|_
 |    |    |    |
_|____|____|____|_
 |    |    |    |

그런 다음 객체를 교차하는 그리드 타일에 삽입하십시오.

_|____|____|____|_
 | @  |    |    |
_|____|____|____|_
 |    |d d |    |
_|____|____|____|_
 |    | d  |  d |
_|____|____|____|_
 |    |    |    |

이제 인근 물체에 대한 쿼리를하려면 근처의 셀을 보면됩니다. 예를 들어, 플레이어의 한 타일 내에서 누가 누구를 확인하기 위해 (@), 전체지도가 아닌 9 개의 타일 만 확인하면됩니다.

/|////|////|____|_
/|/@//|////|    |
/|////|////|____|_
/|////|d/d/|    |
/|////|////|____|_
 |    | d  |  d |
_|____|____|____|_
 |    |    |    |

그러나 세계에 따라이 기술은 상당히 낭비 될 수 있습니다. 빈 셀이 많이있을 수 있습니다. 이것이 문제가되면 더 복잡한 것을 구현할 수 있습니다. 공간 색인.

다른 팁

내가 말하고 싶은 첫 번째 것은 코드가 내부에서 보인다는 것입니다. 왜 로그인하고 세계에서 어떤 클라이언트를 점검 해야하는 높은 수준의 게임 논리 기능이 있습니까? 모든 네트워킹 작업은 게임 로직에서 제거되어 더 높은 수준에서 수행되도록해야하며 게임 내 논리는 현재 플레이하고있는 플레이어와 세계에서만 처리해야합니다. 이것은 당신에게 간단한 질문을 남깁니다.이 두 선수가 서로 가깝습니까? 당신이 이미 가지고있는 것처럼 간단한 거리 점검으로 충분합니다.

다음은 반복의 양을 줄이는 것입니다. 거리는 일반적으로 정류 속성이므로 A와 B 사이의 거리와 B와 A 사이의 거리를 점검 할 필요가 없습니다.이 작업을 수행하려면 첫 번째 루프는 모든 클라이언트를 통과하면 두 번째 루프 만 반복하면됩니다. 첫 번째 클라이언트를 따르는 모든 고객. 이것은 당신이해야 할 반복의 수를 반복합니다.

당신은 또한 당신이 말한 것처럼 이것을 지속적으로 수행 할 필요가 없습니다. 게임이 순조롭게 진행되도록 충분히 종종해야합니다. 움직임 속도가 그다지 높지 않다면 충분히 좋기 위해 몇 초 마다이 작업을 수행하면됩니다.

이것이 여전히 충분하지 않다면 Ianh가 설명한 일종의 공간 해싱 시스템은 귀하가하는 쿼리 수를 줄이는 좋은 방법입니다. 그리드는 가장 쉽지만 일종의 트리 구조 (이상적으로 자체 균형을 잡는)는 또 다른 옵션입니다.

플레이어의 위치를 ​​나타내기 위해 쿼드 트리를 사용해 보십시오.
이에 대한 위키 기사는 다음과 같습니다. 여기.
그것이 하는 일은 공간(평면)을 필요한 만큼 분할하는 트리의 공간(사용자)에 제공한 개체를 유지하는 것입니다.무한대 문제에 관해서는 프로그래밍에서 실제로 무한한 것은 없으므로 사용자가 통과할 수 없는 경계를 정의합니다(좌표에 대해 매우 큰 숫자라도 가십시오. 사용자가 도달하려면 100년 정도 걸릴 것입니다). .

라이센스 : CC-BY-SA ~와 함께 속성
제휴하지 않습니다 StackOverflow
scroll top