Программирование игр, создание игрового движка, OpenGL, DirectX, физика, форум
GameDev.ru / Программирование / Форум / short вмето float для позиции вопрос по синхронизации на больших картах

short вмето float для позиции вопрос по синхронизации на больших картах

FDsagiziПостоялецwww15 мая 201815:16#0
если использовать short для позиции - все бы хорошо, но размер карты 4х4 кв км, и точности уже хватает

думаю использовать сектора, где то 1х1 км. Так вот вопрос, как написать синхронизацию этого дела?

те мы игроку отправили сектор где он находиться, а потом шлем пакеты с позицией внутри сектора, тут  игрок переходит через сектор.
Если сообщения о смене сектора прийдут позже чем сообщения о новых позициях, то игрок займет не верную позицию - тк будет ориентирован не по тому сектору

вопрос, как синхронизировать эту проблему? Пока что на ум только приходит слать координаты сектора если мы стоим рядом с его границей, к примеру 50 метров

FireFenixПостоялецwww15 мая 201815:27#1
FDsagizi
> вопрос, как синхронизировать эту проблему?
посылать своевременно пакеты в порядке очереди? протокол с подтверждением получения? в чём собственно вопрос?

Правка: 15 мая 2018 15:28

DelfigamerПостоялецwww15 мая 201816:13#2
FDsagizi
Слать дельту с последнего подтверждённого пакета?
Сделать нормальный client-side prediction?
ArochПостоялецwww15 мая 201816:40#3
FDsagizi
по изменениям координат на клиенте можно легко определить что координаты принадлежат уже другому сектору, и исходя из них вычислить в какой именно был переход.
kvakvsПостоялецwww15 мая 201816:55#4
Использовать целое число для позиции, но не short.
Тогда 16 бит будет твоя позиция в секторе, а другие 16 бит будет сектор.
Чего экономим биты? Оптимизация под модем 33600 бит/с?

Правка: 15 мая 2018 16:56

Sh.Tac.Постоялецwww16 мая 20181:55#5
FDsagizi
> размер карты 4х4 кв км, и точности уже хватает
6 см точности не хватает? : )

или ты хочешь две координаты туда пихнуть? тогда километр тоже не полезет

Правка: 16 мая 2018 2:04

andreyuПостоялецwww17 мая 201810:53#6
А передавать вместе с координатой индекс (uint8_t в вашем случае достаточно) сектора нельзя?
marikcoolПостоялецwww17 мая 201811:59#7
сектор пиши в 1 байт, итого 256 секторов, это сетка 16х16, 3 шорта на координаты итого всего 7 байт, при размере карты 4к точность 1 сектор выйдет длиной 256, точность координат будет высокая.
да и вообще 6см точности как писали выше должно хватать, тут в cs 1.6 такая же точность и вполне хватает.
FDsagiziПостоялецwww21 мая 201811:44#8
kvakvs
> Чего экономим биты? Оптимизация под модем 33600 бит/с?
Мобильные интернет-ы, + 60 человек на сервере, и постоянное движение

marikcool
> да и вообще 6см точности как писали выше должно хватать, тут в cs 1.6 такая же
> точность и вполне хватает.
Представь машину, которая прыгает из стороны в сторону на 6 см

> сектор пиши в 1 байт, итого 256 секторов, это сетка 16х16, 3 шорта на
> координаты итого всего 7 байт, при размере карты 4к точность 1 сектор выйдет
> длиной 256, точность координат будет высокая.


Спасибо, отличное решение, и очень хорошая точность выходит - около 1 см

вот код, наверное не самая быстрая реализация:

  public struct Pose{
    const int seg_count = 16; // 16 x 16
    const float max_range = 4000; // max z and z pose, -v to v
    const int max_val = 65535; // 65535
    const float max_y_range = 250; // y value not use segment, because our game not use very higt positions

    // test
//    const int seg_count = 3;
//    const float max_range = 15;
//    const int max_val = 100; // 65535

    const float sector_size = max_range * 2f / (float)seg_count;
    const float sector_2_ushort = (float)max_val / sector_size;
    const float ushort_2_sector = sector_size / (float)max_val;

    const float y_2_ushort = (float)max_val / (max_y_range * 2);
    const float ushort_2_y = (max_y_range * 2) / (float)max_val;

    public Vector3 pose{
      get{
        return Read();
      }
      set{
        Write (value);
      }
    }

    // real data
    public ushort x, y, z;
    public byte index;

    public static Pose New(Vector3 val){
      var ret = new Pose();
      ret.Write(val);
      return ret;
    }
      
    public Vector3 Read(){
      if(index_2_secotor == null)
        initArr();
      var offset = index_2_secotor [index];
      var pos = new Vector3 (offset.x, (float)y * ushort_2_y - max_y_range, offset.y);

      pos.x += (float)x * ushort_2_sector;
      pos.z += (float)z * ushort_2_sector;

      return pos;
    }

    public void Write(Vector3 pos){
      pos.y = Math.Max(Math.Min(max_y_range, pos.y), -max_y_range) + max_y_range;
      y = (ushort)(pos.y * y_2_ushort);

      pos.x = Math.Max(Math.Min(max_range, pos.x), -max_range);
      pos.z = Math.Max(Math.Min(max_range, pos.z), -max_range);

      int x_sector = GetSector (pos.x);
      int z_sector = GetSector (pos.z);
      index = (byte)((z_sector * seg_count) + x_sector);

      if(index_2_secotor == null)
        initArr();
      var offset = index_2_secotor [index];
      pos.x -= offset.x;
      pos.z -= offset.y;

      x = (ushort)(Math.Min (pos.x, sector_size) * sector_2_ushort);
      z = (ushort)(Math.Min (pos.z, sector_size) * sector_2_ushort);
    }

    public static int GetSector(float v){
      float alpha = (max_range + v) / sector_size;
      var ret = (int)alpha;
      if (ret == seg_count) 
        return seg_count - 1;
      return ret;
    }

    static Vector2 []index_2_secotor =null;
    static void initArr(){
      if(index_2_secotor != null)
        return;
      index_2_secotor = new Vector2[seg_count * seg_count];
      for (var z = 0; z < seg_count; z++) {
        for (var x = 0; x < seg_count; x++) {
          int idx = z * seg_count + x;
          index_2_secotor [idx] = new Vector2 ((float)(x * sector_size) - max_range, (float)(z * sector_size) - max_range);
          //Debug.Log ("Idx2Sector " + idx + " val " + index_2_secotor [idx]);
        }
      }
    }
  }

/ Форум / Программирование игр / Сеть

2001—2018 © GameDev.ru — Разработка игр