Sign in to follow this  

Adding networking to my game

This topic is 2034 days old which is more than the 365 day threshold we allow for new replies. Please post a new topic.

If you intended to correct an error in the post then please contact us.

Recommended Posts

I just started working on my RPG and I want it to be multiplayer. I haven't put too much work into it too far because I want to get the networking down first. Basically it's only sprites moving around on a map with basic collision detection. I downloaded KryoNet and got it so I can send and receive objects and it reacts accordingly to whatever object is passed in from the client to the server.

I literally have no idea how the logic for this works, as this is my first networked project. Any suggestions would help me greatly, I was thinking of going with a single client/server in one and having the user be able to select hosting a game or joining a game that is already made.

Any resources you can show me would help a lot as well.

Thanks.

Share this post


Link to post
Share on other sites
Okay, I'm pretty sure I've got it figured out now. I just need to know what I should be sending to my server? Like say the client-end user presses an arrow key to move in a direction. How should I be sending that to the server? Would I make another class to represent directions or something like that? Or would I just send the whole player class and pass it into some update method for the class? I really have no idea what I'm doing here.

Thanks

Share this post


Link to post
Share on other sites
Typically, you define a protocol. Part of a protocol is typically a PDU (packet data unit) definition. A typical implementation of a PDU is a C-style "struct," or a defined binary serialization format of some sort. Another part is the surrounding framing -- letting the receiver know what kind of PDU is coming in, and how much data it is, so the PDUs don't run together.

A typical PDU framing header might look like:

[code]byte: type
byte: datalength
byte[]: data
[/code]

What "data" means depends on the "type" field. For example, you can define a byte with bit values for different keys:

[code]
enum KeyType {
KeyLeft = 0x1,
KeyRight = 0x2,
KeyUp = 0x4,
KeyDown = 0x8,
KeyJump = 0x10,
KeyAction = 0x20
};

enum PduType {
PduTypeKeys = 1,
PduTypeChat = 2
};
[/code]

At this point, you'd send a PDU of type 1, containing a single byte, which is the bitwise OR of the keys that are down. You could also send a PDU of type 2, where the "data" would be the text of a chat message from the client.

The network interface layer then has to translate between whatever the input/actor/entity system uses for data, and the PDU format. Then it has to translate back on the receiving side. This translation mechanism is generally known as "marshaling" and is related to, but not the same thing as, serialization. Note that some serialization mechanisms use 10x or even 100x the amount of storage/bandwidth as a plain marshaling system, so don't just apply some random serialization library that happens to be available.

Share this post


Link to post
Share on other sites
I still don't really get what I need to do. Like for example I have a method in my client like this.

[CODE]
public void sendSomething(Object obj){
try {
client.start();
client.connect(500, "192.168.2.5", 7187);
client.sendTCP(obj);
client.stop();
} catch (IOException e) {
e.printStackTrace();
}
}
[/CODE]

And I have my server set up like this

[CODE]
public void init(){
server = new Server();
server.start();
try {
server.bind(7187);


server.addListener(new Listener(){
public void received (Connection connection, Object object) {
if(object instanceof String){
System.out.println(object);
}
}
});

} catch (IOException e) {
e.printStackTrace();
}
}
[/CODE]

That's just for testing purposes, but say I want to like I said, pass in the player and move it accordingly, what would I do? Or am I going about this all wrong? I'm really confused here.

Share this post


Link to post
Share on other sites
You set up the connection at the beginning, and then you keep it open. You send each new command/message on the same connection. Same thing with receiving, you "drain" the connection each time through your main loop, and decode the messages you receive this way, and hang on to whatever data is left at the end, as it will be the beginning of whatever message comes next.

Share this post


Link to post
Share on other sites
Firstly, note that I don't use C++. I use Python, so some terminology will differ, and you may need to add intermediary steps to what I write.

Most of the game events will work along these lines:

EVENT -> CONDITION -> EXECUTION (-> FEEDBACK)

whereby in your case, an event would be a keypress, a condition verifies if the event is valid and execution is movement of the player.
Many multiplayer games will transmit only the client events (Keyboard inputs, Mouse position, Mouse inputs). Then, the server acts accordingly.
Simply establish first a protocol which enables you to identify a packet as an event packet, connection request packet, disconnect request packet and so on.
In python, I use a list (A form of an array) with the first index as an integer that defines the packet type. The server has a list of callbacks which are executed from a dictionary (list and dictionaries are differing forms of an array, lists only have integer indexes, and both are single dimensional) e.g 0 -> DoMovement()
You want to isolate the processing of events from the feedback; the server can update the client of the world changes at a slower rate than it needs to sample inputs.

Share this post


Link to post
Share on other sites
[quote name='stein102' timestamp='1337489732' post='4941584']
Okay, I see what you're saying there. But I still don't understand how I can tell the server to move the player. Blah, networking is really confusing.
[/quote]

In pseudo code, if you want to move a player (only passing minimal info here), you would do something like this:
[code]
// defines the packet type being send
enum etPacketType
{
MOVE_PLAYER_TYPE,
BROADCAST_CHAT_TYPE
};

// packets defined in client and server:
struct tPacketHeader
{

etPacketType PacketType;
uint8_t DataLength;
}

struct tPlayerMoveData
{
uint32_t PlayerIdToMove;
double PositionX;
double PositionY;
double VelocityX;
double VelocityY;
}

struct tMovePacket
{
tPacketHeader PacketHeader;
tPlayerMoveData PlayerMoveData;

}

// Client code, where the MovePacket has been filled out
void MovePlayer(tMovePacket &PlayerToMove)
{
// Send this data to server, tell it to move this player
DataSend(ServerSocket, &PlayerToMove, sizeof(tMovePacket));
}

// in Server code, assuming you get notified when data comes in
void ReadData()
{
tPacketHeader PacketHeader;
tPlayerMoveData PlayerMoveData;

// Read the PacketHeader only 1st
RecvData(ClientSocket, &PacketHeader, sizeof(tPacketHeader);

switch (PacketHeader.PacketType) {
case MOVE_PLAYER_TYPE:
// Read the rest of the data into PlayerMoveData
RecvData(ClientSocket, &PlayerMoveData, sizeof(tPlayerMoveData);
// Now handle moving the Player given by playerId, located at the given positions,
// and mvoe it the given velocities
HandlePlayerMove(PlayerMoveData);

// handle others below
default:
break;
[/code]

This is just a general idea of what you could do. There are tons of ways to do this, like just sending the key presses, and have the server move the player based on the keys it gets.

Share this post


Link to post
Share on other sites
Thanks everyone! I got it figured out now. It was just a little difficult to wrap my head around how all the networking and packets worked. I have another question now though:

Am I supposed to have a sort of game or default packet that sends every time the sever goes though the game loop that updates all the game data? Like say I would have a packet sort of like this

[CODE]
public static class Packet0Default{
allPlayers;
allNPCs;
}
[/CODE]

Where those are arrays of the respective types, filled with all the game players and their data? Or would I just need to send the new player data to all connected users when the player moves?

Share this post


Link to post
Share on other sites
[quote name='stein102' timestamp='1337653460' post='4942061']
Thanks everyone! I got it figured out now. It was just a little difficult to wrap my head around how all the networking and packets worked. I have another question now though:

Am I supposed to have a sort of game or default packet that sends every time the sever goes though the game loop that updates all the game data? Like say I would have a packet sort of like this

[CODE]
public static class Packet0Default{
allPlayers;
allNPCs;
}
[/CODE]

Where those are arrays of the respective types, filled with all the game players and their data? Or would I just need to send the new player data to all connected users when the player moves?
[/quote]

Depends on the game type, but, typically, you would only send changes. For example, for player movement, you send change in velocities, for bullets, you send when a bullet is fired, where it originated, what time it originated, and it's velocity.

Occasionally, you might send a world-state packet just to make sure everyone is in sync, but that would be on the order of seconds (every 5-10 seconds, or something like that)

Share this post


Link to post
Share on other sites

This topic is 2034 days old which is more than the 365 day threshold we allow for new replies. Please post a new topic.

If you intended to correct an error in the post then please contact us.

Create an account or sign in to comment

You need to be a member in order to leave a comment

Create an account

Sign up for a new account in our community. It's easy!

Register a new account

Sign in

Already have an account? Sign in here.

Sign In Now

Sign in to follow this