Networking Question

Vēlies radīt spēli, bet nezini ar ko sākt? Sperot pirmos soļus, vari meklēt padomu šeit
Message
Author
CodeWolf
Posts: 119
Joined: 10 Dec 2010, 19:10
Location: LV-Riga-Marupe

Re: Networking Question

#51 Post by CodeWolf » 30 Jan 2012, 19:17

mm ,pag tak iepriekš minēji ka viss kods jaapvieno kopā..
vai tad nevajadzēja būt tā..?
1. norādam pozīcijas
2. saspiežam tās vienā intā..//pos_pack
3.pos_pack sadalam bitos..//initBits()..storeBits untt
4.nosūtam..//chara ,izmerā..
//OpenGL

bubu
Guru
Guru
Posts: 398
Joined: 07 Dec 2010, 11:54

Re: Networking Question

#52 Post by bubu » 31 Jan 2012, 00:04

Tieši tā. Pareizi esi sapratis.

CodeWolf
Posts: 119
Joined: 10 Dec 2010, 19:10
Location: LV-Riga-Marupe

Re: Networking Question

#53 Post by CodeWolf » 31 Jan 2012, 20:00

nu bet tādā gadījumā sanāk sūtīt to lielo skaitli kuru viņš nemaz neļauj nosūtīt. Jo Izsūtāmo vai saņemamo failu max .. to neatļauj
Limits +100 ir x, y un z mainīgajiem. Nevis pos_packet.
+ kur tas ir minētsēts ka es tieši x,y,z definēju to +100-100 katrai vertibai?
Pēc shemas kā iepriekš rakstiju

Code: Select all

int xi=(int)(x*10),yi=(int)(y*10),zi=(int)(z*10);
pos_packet_0 = xi | (yi << 10) | (zi << 20);
Paka0->write(pos_packet_0,-100.0f,+100.0f,0.01f,SPW_PK);//SPW_PK = GameMessageID -130
//OpenGL

bubu
Guru
Guru
Posts: 398
Joined: 07 Dec 2010, 11:54

Re: Networking Question

#54 Post by bubu » 31 Jan 2012, 20:11

Nepareizi esi tu tur uzrakstījis kodu.
Vispirms vajag pakā pa bitiem sarakstīt individuāli to x/y/z (katram norādot kautvai savu min/max/prec). Paka uztur buferi, kuru tu vēlāk vari aizsūtīt pa soketu.

Reku biju rakstījis kas un kā: http://forums.gamedev.lv/viewtopic.php?p=1658#p1658

Code: Select all

Paka0->writeInt(SPW_PK, 5);
Paka0->writeFloat(x,-100.0f,+100.0f,0.01f);
Paka0->writeFloat(y,-100.0f,+100.0f,0.01f);
Paka0->writeFloat(z,-100.0f,+100.0f,0.01f);

socket->send(Paka0->getBuffer(), Paka0->getBufferSize());
Saspiešana intā notiek writeFloat'ā + turpatās no tā int'u sadala pa bitiem un ieraksta iekšējā buferī. writeInt paņem tik cik tev bitus norāda. Manā piemērā piecus - tas dos iespēju nosūtīt max 32 id vērtības.

CodeWolf
Posts: 119
Joined: 10 Dec 2010, 19:10
Location: LV-Riga-Marupe

Re: Networking Question

#55 Post by CodeWolf » 31 Jan 2012, 23:39

Njam., meiģināju izveidot tā kā teici bet velāk atsevišķi izsaucot "Send" komandu izmetas errors..
tā pat arī meiģināju uztaisīt. write3floats( ar 3 verībam)
vēlāk tās visas reizē izsūtot..
šādā veidā

Code: Select all

bsOut.Write((RakNet::MessageID)GameMessageIDs);
	bsOut.Write((char*)buffer_1,BBC_1);//x
	bsOut.Write((char*)buffer_2,BBC_2);//y
	bsOut.Write((char*)buffer_3,BBC_3);//z

	peer->Send(&bsOut,HIGH_PRIORITY,RELIABLE_ORDERED,0,packet->systemAddress,false);
jo es atsevišķi send funkciju nevarēju iegūt viņa vienkārši tad bija 0 vai tukš sūtijums
bet tad man problēmas radās šo te nolasīt..
meiģināju gan ar float gan void(x,y,z-100......)
izsaukt bet neizdevās..

sāku domāt.. varbūt izdarīt nedaudz savādāk
1.klientam pieslēdzoties nosūtīt tīrus 3 floatus //kā spawn poziciju (12baitu izmērā)
2. un tad
sūtīt saspiesto skaitli kuru iepriekš esmu apzīmējis
piem pie pozīcijām
0-stāvēt
1-iet pa dioganāli
2-uz augšu
3-uz leju
untt
un ~ iekļauties tajos -10 /+10
un iekš klienta rēķināt pārējo pozīcijas..

nedaudz arī palasīju RakNet pamācības..
nesaprotu to kā viņi var nosūtīt floatus struktūrā (lielos daudzumos neko nesaspiežot)

unsigned char useTimeStamp; // Assign this to ID_TIMESTAMP
RakNet::Time timeStamp; // Put the system time in here returned by RakNet::GetTime()
unsigned char typeId; // This will be assigned to a type I've added after ID_USER_PACKET_ENUM, lets say ID_SET_TIMED_MINE
useTimeStamp = ID_TIMESTAMP;
timeStamp = RakNet::GetTime();
typeId=ID_SET_TIMED_MINE;
Bitstream myBitStream;
myBitStream.Write(useTimeStamp);
myBitStream.Write(timeStamp);
myBitStream.Write(typeId);
// Assume we have a Mine* mine object
// If the mine is at 0,0,0, use 1 bit to represent this
if (mine->GetPosition().x==0.0f && mine->GetPosition().y==0.0f && mine->GetPosition().z==0.0f)
{
myBitStream.Write(true);
}
else
{
myBitStream.Write(false);
myBitStream.Write(mine->GetPosition().x);
myBitStream.Write(mine->GetPosition().y);
myBitStream.Write(mine->GetPosition().z);
}
myBitStream.Write(mine->GetNetworkID()); // In the struct this is NetworkID networkId
myBitStream.Write(mine->GetOwner()); // In the struct this is SystemAddress systemAddress

This can potentially save us sending 3 floats over the network, at the cost of 1 bit.
+

Code: Select all

You can also write bits. Most of the time you will not care about this.
http://www.raknet.net/raknet/manual/bitstreams.html
:?
//OpenGL

bubu
Guru
Guru
Posts: 398
Joined: 07 Dec 2010, 11:54

Re: Networking Question

#56 Post by bubu » 01 Feb 2012, 02:11

Nesaprotu tavu kodu. Kas tev tur par tik daudz buferiem? Vienu tikai vajag.
Reku tev gatavs un strādājošs kods ar visu lietošanas piemēru. Kļūdu gadījumus, protams, neapstrādāju, un tā vietā lietoju assert. Tavā ziņā ir tas, kā to labot, ja vajadzīgs. Ar optimizāciju arī neaizrāvos, uzsvars uz koda saprotamību.

Code: Select all

#include <string.h>
#include <assert.h>
#include <math.h>
#include <stdio.h>

class BitBuffer
{
public:
    BitBuffer()
    {
        reset();
    }
    
    void reset()
    {
        pos = 0;
        maxPos = 8*MAX_BYTE_COUNT;
        memset(buf, 0, sizeof(buf));
    }
    
    void assign(const unsigned char* bytes, int byteCount)
    {
        assert(byteCount <= MAX_BYTE_COUNT);
        
        pos = 0;
        maxPos = byteCount * 8;
        memcpy(buf, bytes, byteCount);
    }
    
    void writeInt(unsigned int x, int bits)
    {
        assert(bits <= 32);
        assert(x < (1U<<bits));

        for (int i=0; i<bits; i++)
        {
            putBit((x >> i) & 1);
        }
    }
    
    void writeFloat(float x, float min, float max, float prec)
    {
        assert(x >= min && x <= max);

        int bits = (int)ceilf(logf((max - min) / prec) / logf(2.0f));
        writeInt((unsigned int)(0.5f + (x - min) / prec), bits);
    }
    
    unsigned int readInt(int bits)
    {
        assert(bits <= 32);

        unsigned int x = 0;
        for (int i=0; i<bits; i++)
        {
            x |= getBit() << i;
        }
        return x;
    }
    
    float readFloat(float min, float max, float prec)
    {
        int bits = (int)ceilf(logf((max - min) / prec) / logf(2.0f));
        return min + readInt(bits) * prec;
    }
    
    const unsigned char* getBuffer() const
    {
        return buf;
    }
    
    unsigned int getBufferSize() const
    {
        return (pos+7)/8;
    }
    
private:
     void putBit(int bit)
     {
         buf[pos/8] |= bit << (pos%8);
         pos++;
         
         assert(pos < maxPos);
     }
     
     int getBit()
     {
         assert(pos < maxPos);

         int bit = buf[pos/8] >> (pos%8);
         pos++;
         return bit & 1;
     }
     
     static const int MAX_BYTE_COUNT = 128; // max 1024 bits
     unsigned char buf[MAX_BYTE_COUNT];

     int pos;
     int maxPos;
};


int main()
{
    BitBuffer packet2;

    {
        int id = 12;
        float x = 1.0f;
        float y = -55.5f;
        float z = 77.0f;

        BitBuffer packet;

        packet.writeInt(id, 4); // id = [0..15]
        packet.writeFloat(x, -100.0f, +100.0f, 0.1f);
        packet.writeFloat(y, -100.0f, +100.0f, 0.1f);
        packet.writeFloat(z, -100.0f, +100.0f, 0.1f);

        // te suuti otrai pusei
        //socket->write(buf1.getBuffer(), buf1.getBufferSize());
        
        // otraa puse sanjem un ieraksti buferii
        packet2.assign(packet.getBuffer(), packet.getBufferSize());
    }

    int id;
    float x, y, z;

    id = packet2.readInt(4);
    x = packet2.readFloat(-100.0f, +100.0f, 0.1f);
    y = packet2.readFloat(-100.0f, +100.0f, 0.1f);
    z = packet2.readFloat(-100.0f, +100.0f, 0.1f);

    printf("%i %.1f %.1f %.1f\n", id, x, y, z);
   
}
Ļoti precīzi saglabā, aizsūta un izdrukā tavu id un x/y/z skaitļus 5 baitos (izmēru atgriež getBufferSize() metode).

RakNet'a koda gabalā tiek ietaupīts uz to, ka ja visas trīs pozīcijas x/y/z komponentes ir 0, tad tas tiek aizsūtīts īsāk. Nav diezko laba "optimizācija".

CodeWolf
Posts: 119
Joined: 10 Dec 2010, 19:10
Location: LV-Riga-Marupe

Re: Networking Question

#57 Post by CodeWolf » 01 Feb 2012, 21:23

es jau teicu ka mēģināju.. to ka iespējamo varinatu ,tāpēc tur bija tik daudz bufferu.. Jo kodu taisiju pec tada principa kā
-> sūtīt 1ienu //apvienoto intu vērtību..
un neko vairāk.. tikai vienai vertibai

hmh.. īsti nesapratu izsūtīšanas vietu..
tur kur ir tas buf1.getBuf..
// te suuti otrai pusei
//socket->write(buf1.getBuffer(), buf1.getBufferSize());

// otraa puse sanjem un ieraksti buferii
packet2.assign(packet.getBuffer(), packet.getBufferSize());
Tas ir kautkāds random buferis(chars) vai vienkārši..klases pārstāvis
jo sūtot Paku kā tādu, otrā pusē neko nesaņemu..
parbaudīju savienojumu..parastās komandas strādā (//bsOut.Write(..kkads floats), bet tad kad velos nosutit paku
klienta puse x,y,z=-100. ... ... ..
//OpenGL

bubu
Guru
Guru
Posts: 398
Joined: 07 Dec 2010, 11:54

Re: Networking Question

#58 Post by bubu » 01 Feb 2012, 21:33

Es nesaprotu, ko tu nesaproti.

Tev ir socket klase kautkāda ar vismaz šādu funkcionalitāti, pareizi?

Code: Select all

class Socket {

    // aizsūta no buffer bufera size baitus
    void Write(const unsigned char* buffer, unsigned int size);

    // mēģina nolasīt maxSize baitus buferī, un atgriež nolasīto baitu skaitu
    int Read(unsigned char* buffer, unsigned int maxSize);
}
Tad nu sūtīšanas vietā raksti:

Code: Select all

BitBuffer buf;
buf.writeInt(id, 5);
buf.writeFloat(x, ...);

socket->Write(buf.getBuffer(), buf.getBufferSize());
Saņemšanas vietā raksti:

Code: Select all

unsigned char temp[100]; // cik nu tev tur max baiti atnāk no tīkla
int size = socket->Read(temp, sizeof(temp));
BitBuffer buf;
buf.assign(temp, size);

id = buf.readInt(5);
x = buf.readFloat(...);
Kas te ir nesaprotams?

CodeWolf
Posts: 119
Joined: 10 Dec 2010, 19:10
Location: LV-Riga-Marupe

Re: Networking Question

#59 Post by CodeWolf » 01 Feb 2012, 23:33

hmh viss strada labi
vienīgi nolasot
ja izmantoju

Code: Select all

bsIn.Read((char*)temp,sizeof(temp)); 
tad visas vertibas nemaz chara netiek ierakstītas..
ja izsaucu

Code: Select all

bsIn.Read((char*)temp,sizeof((char*)temp)); 
tad iegūstu pie izmēra 4 kas itkā ir par maz jo salīdzināju saņemtos čarus un pēdējā vērtība atšķīrās
char temp([0]76'L' | [1]126'~' | [2]189'1/2'[3]55'Q')
vietā saņēmu
char temp([0]76'L' | [1]126'~' | [2]189'1/2'[3]81'Q')
vēlāk nosverot sapratu ka trūkst 1 b..
tāpēc izdomāju to pieskaitīt klāt..

Code: Select all

bsIn.Read((char*)temp,sizeof((char*)temp)+1); 
tad viss nosūtījās.. bet es nēsmu pārliecināts vai tā drīkstēja darīt.. :)
+ pirmstam kodā redzēju to ka ar bitiem apzīmē inta izmēru ..to ierobežojot
packet.writeInt(id, 4); // id = [0..15]
nevari ludzu pateikt pēc kā es varu aprēķināt to cik daudz intus es iegūšu pēc attiecīgā izmēra..?
//OpenGL

bubu
Guru
Guru
Posts: 398
Joined: 07 Dec 2010, 11:54

Re: Networking Question

#60 Post by bubu » 01 Feb 2012, 23:43

Paskaties, ko sizeof dara, un ko tas nozīmē, pirms lietot savu kodu, kuru tu, kā izskatās randomā raksti... Kamon, sizeof((char*)temp) ???

Code: Select all

#include <stdio.h>

int main()
{
    char c;
    char* buf;
    char big[100];

    printf("%i\n", sizeof(c));
    printf("%i\n", sizeof(buf));
    printf("%i\n", sizeof(big));
}
Vai tagad saproti atšķirību, starp "char c", "char* c", un "char c[100]" ?
nevari ludzu pateikt pēc kā es varu aprēķināt to cik daudz intus es iegūšu pēc attiecīgā izmēra..?
Kas ir "cik daudz", un kas ir "pēc attiecīgā izmēra"? Cik daudz no kurienes? Kas ir tas ko tu skaiti? Kādus intus? Kas par izmēru?

Post Reply

Return to “Iesācējiem / For beginners”