This has been driving me nuts. I've been working on creating a 3d game highly centered around a physics engine in the spirit of Robot Arena 2. I'm currently using DarkBasic Professional, but I'm running into a roadblock when it comes to the multiplayer side of things, since I have to set up packets myself.
A certain tutorial I read spoke about arranging all my data to send into a string with asterisks for seperators. I'm able to send strings, numbers, etc, but I'm thinking that packing as much info as I can into one reasonable packet is my best move. I can also send "memblocks", which I'm wondering if there might be a more efficient way of storing data than in a string. In either case, I'll also need an efficient way of parsing this data back out into my entities on the other end.
With the physics system (Newton Game Dynamics), I'm figuring my best bet will be to transmit positions and rotations of "active" objects, update when new objects are added, update when objects are deleted, as well as inputs from players. This is going to get complex when I have several objects with multiple joints moving around. Currently, I store all my "entities" in an array. Entities are a custom data type that holds data about each of the (potentially 3) physics bodies that make up the entity. I plan to cycle through all my entities, determine if their bodies are "active" or not, and then send data about them.
I don't know if anyone on BYOND has worked with DarkBasic at all, but I think my problem is more universal about how I'd effectively parse a text string out to a number of variables.
Any help would be appreciated, thanks!
ID:185129
Apr 20 2006, 4:19 pm
|
|
In response to Crispy
|
|
I'm only planning on running this on Windows PC's, I doubt Darkbasic runs on anything else.
What you said about "packed representations" makes sense. I was thinking about how a string is stored, just in a text file, with each character having so many possibilities, and it seemed really inefficient. So... next question is... How do I do that? Hehe, if you're able to explain it in some sort of abstract terms, or how you might accomplish it in another language, that'd help. I may end up having to fiddle with memblocks in Darkbasic, but if I can "pack" my numbers another way, that seems reasonable. Also, currently, I'm taking the actual coordinates of objects, multiplying them by 100, converting them to integers, and then sending that, to be divided by 100 on the other end, rather than sending data for 9 digits of floating point decimal places. Is this a common practice? |
In response to DerDragon
|
|
I don't know what memblocks are, but just from the name they sound like they could be useful.
One of the most straightforward ways to pack an integer is to use bit-level operations to isolate each byte of the int, convert it to a 1-byte ASCII string, and concatenate all of those strings together. Then you get a 4-byte string which is the packed representation of the integer. It will look like gibberish if you try to display it, of course. Here's some D code (D is similar to C, but IMO better) adapted from a project I've been working on that demonstrates the bit-level operations used: packet[1] = (value>>24)%256; packet[2] = (value>>16)%256; packet[3] = (value>>8)%256; packet[4] = value%256; The >> is the right-shift operator (which chops off bytes after the one we want to isolate), and the %256 at the end chops off bytes before the one we want to isolate. Each byte is isolated and saved to the string in turn. Often you wouldn't do this yourself; there is typically some kind of API call which can pack data for you. Also, currently, I'm taking the actual coordinates of objects, multiplying them by 100, converting them to integers, and then sending that, to be divided by 100 on the other end, rather than sending data for 9 digits of floating point decimal places. Is this a common practice? No, that's actually pretty inefficient. Floating point numbers have their own internal representation which would be preferable to send. Off the top of my head I don't know how you'd pack a float into a string in a Basic-like language. Look for an API call. |
In response to Crispy
|
|
Thanks, I looked into memblocks more, and they are definitely the way to go. Each update for a whole entity will be 76 bytes, IF it's a 3 part entity, which most of them are not. Most things will only be 28 bytes to update. I can live with that.
Thanks Crispy! |
In response to DerDragon
|
|
No worries, I'm glad you found a good solution.
|
In response to Crispy
|
|
packet[1] = (value>>24)%256; Ouch! Much faster and makes more intuitive sense to mask off the extra bits :P. packet[1] = (value>>24)&0xFF; packet[2] = (value>>16)&0xFF; packet[3] = (value>>8)&0xFF; packet[4] = value&0xFF; |
I don't know if anyone on BYOND has worked with DarkBasic at all, but I think my problem is more universal about how I'd effectively parse a text string out to a number of variables. Not sure if you can but it would probably be a lot cleaner and faster to work with raw bytes than strings. Since no parsing is neccessary if your datagrams are properly set up you can index right into the data you need to get at. |
In response to Crispy
|
|
(If not, you can ignore Endianness and it will still work - but that's bad karma. :-) ) Heh yeah especially given the internet standard is big endian while windows machines are little endian. Good practice to convert to the network format before transmitting data and then to whatever you need after recieving. |
In response to Theodis
|
|
A good optimising compiler should recognise that equivalence (not that it would matter anyway - this is not speed-critical code, and it's bounded by the network performance anyway) and I don't know about "intuitive sense", but yes, that is slightly better. =)
|
Usually one would send packed representations of numerical data. Strings are sometimes delimited, but it's also common to prefix the string with its length (again, using a packed numerical representation).
By packed, I mean as it actually is stored in memory. That way a standard C int on a 32-bit machine would always take up exactly 4 bytes; no more, no less. That's much more efficient than converting it to a string, in which case it could take up anywhere from 2 bytes (one for a digit and one for a separator) to around 12 bytes for a large negative number; and it would be slower to parse, too.
A string is a string is a string, though; its "packed" representation is generally the same as its string representation. (Ignoring compression of course, but usually compression is more trouble than it's worth for games - it takes too long to encode and decode to be worth the trouble.)
You do need to worry about endianness when doing this, assuming that your game is intended to run on multiple platforms. (If not, you can ignore Endianness and it will still work - but that's bad karma. :-) )