Ambiera Forum

Discussions, Help and Support.

Create a new account, Search, or Login:
Name: Password:
Ambiera Forum > CopperCube > Programming and Scripting
Question on multiplayer: are WebSockets useful for creating a multiplayer game?
Author Text

dekon_17
Registered User
Quote
2022-07-21 07:24:55

I know, asking this question might result in little to no response (I mean, not so much people here know how to make multiplayer on CopperCube, as far as I know), but I will try to ask it anyways.

So, since socket connection is the only viable choice for FPS games, I tried to research on possible ways to make at least something with them. As it turns out, there are WebSockets available in JavaScript, which is neat. But here's the thing: firstly, I don't know if CopperCube support this kind of stuff, and secondly: all the examples that I found in the internet were some sort of browser applications (like chats or something).

This makes me wonder: is it even possible to use WebSockets for multiplayer in CopperCube games?


just_in_case
Moderator
Quote
2022-07-21 07:32:46

For webGL-based games, I think it is definitely possible. Here is a link to the game multiplayer game that was created about 6 years ago using CopperCube. Maybe you can find something useful and interesting in there.

https://github.com/JohannesHoppe...


dekon_17
Registered User
Quote
2022-07-21 07:48:34

Well, that's neat, since I have one WebGL project in development.

But will it work on Windows? I mean, what I found in internet was something like using URL of a website (something like wss:/site.com, I don't remember), which initially made me think if it is usable for Windows games.


okeoke
Registered User
Quote
2022-07-21 10:15:50

Unfortunately, WebSocket will not work on any targets other than browser.

The reason for that is that WebSocket API is a part of modern browser functionality, not Coppercube itself. Coppercube also uses an old JS (definitely pre-ES5) version of JS and lacks a lot of modern JS capacities also, like for example JSON object support which is used for data serialization which is crucial for a multiplayer project.

Actually you can sort of make it work by running your game in some web application wrapper like electron https://www.electronjs.org/. You can even target the platforms not officially supported by CCB (like linux for ex) that way.


dekon_17
Registered User
Quote
2022-07-21 10:21:02

Well, that's unfortunate. So... Is there any other way to make a socket-based multiplayer? As far as I know, there is just WebSocket in JavaScript. Does this mean that there is no normal way to make a socket-based multiplayer?


dekon_17
Registered User
Quote
2022-07-21 10:36:27

Okay, I have a really bad idea about multiplayer.

It's probably bad because it is based around HTTP server and ccbDoHTTPRequest command. I suppose that this is a bit terrible way to make multiplayer on Windows, but this is the only thing that I came up with.


okeoke
Registered User
Quote
2022-07-21 10:38:59

I guess, the best option is use webgl target and wrapper like electron.

Another option is to use a third party tool to create a websocket connection. There is also no way to create an IPC so the only way to communicate to it is by using the file system.
You can find a demo and simple implementation of this approach here: https://www.youtube.com/watch?v=bzprSc2VAdI&ab_channel=AlexIvanov. Download link is in the comments. I used node js to establish a connection. Actually, I would not suggest using this approach. If desktop is a must better use electron.


okeoke
Registered User
Quote
2022-07-21 11:08:51

http is not that bad tbh.

The main thing you should not send a new request every frame. Instead you save your game state send it to a server every 100 ms or so.

For example, let's say you have a simple game: two players p1 and p2. They can shoot to each other, the one who's not dead wins.

What can you do:
Server side. You need to create a simple server app using php, nodejs, .net or whatever you like to use. It will not be a real "server" just a tool for interchanging the data between clients (i.e. players). In-game it will use only 1 endpoint, call it update. There should obviously be others which will allow you to establish a connection, create a lobby and etc, but I think you will figure it out.

Client side. You need to send your player data to the other guy. There are multiple things to send: your character rotation, position, and animation and also data which could be described as events: player fires a gun, player takes damage, etc. So:

For player data (position, rotation, animation):
1. Client 1 side: you should have a function which gets your local player character position, rotation and current animation and sends it to the server every 100 ms (/update endpoint). You also need to assign both client IDs (1 and 2 for example);
2. Server side: as server receives this data it saves it to a variable matched by player id.
var player1data = {
posx: 1,
posy: 2,
posz: 3
rotx: ... etc
}
var player2data = {
posx: 10,
posy: 2,
posz: -23
...etc
}

3. Client 2 side: client two sends it's data the same way as client 1 (/update). In response to this call it receives player 1 data.
4. You now have player 1 data on player 2 client. But you can't directly apply it,since we're only sending it 100 ms and moving/rotation would be jumpy in that case. For that on client you create a states array, which stores player 1 data along with the time than data was received.
Something like:

// an array to store your states
var stateArray = [];
// update endpoint call function
// you send playerId and playerData to the server using url parameters
ccbDoHttpRequest('yourserverhostorip/update?playerId=' + playerId + '&data' + playerData, function(receivedData) {
// received data from the remote player
// parse receivedData to js object somehow so you can
// access remote player position, rotation and animation
// parse is just to mock - it's not a real function
var parsedData = parse(receivedData);
// save remote player data snapshot time
parsedData[time] = (new Date()).getTime();
stateArray.push(parsedData);
})



dekon_17
Registered User
Quote
2022-07-21 11:11:49

I've looked the behaviors and stuff from that video, and I must say, if I will be able to understand some things from here, I can actually try to do something based on it. Thanks for that.


dekon_17
Registered User
Quote
2022-07-21 11:16:58

Oh, wait, HTTP method is not bad? That's surprizing. But considering that I will need to do this about every 100 ms, this won't suit me. You see, I am trying to create a bit dynamic game, so, it will be a lot I guess. Still, I must try that as well. Maybe I will use it in my other projects, who knows?

Also, how do I send the data to server this way? I mean, HTTP request is understandable, it gives me data, but how do I send it?


okeoke
Registered User
Quote
2022-07-21 11:40:48

5, So now you can have multiple states with data stamps. Let's talk only x position for the simplicity it's applied to a rotation same way. So you have 2 snapshots. At 0 ms your player 2 x position is 0 at 100 ms your player 2 position is 10. So for simplicity let's say the player characters moves lineary, there will it be at for example 50 ms? - in the middle of that distance. On 33 ms it will be at 1/3 of the distance. I.e. we can get a position at any time using linear interpolation. The function used to do that is usually called lerp. You can find js implementation of it in the Internet. I guess something like this would work: https://github.com/mattdesl/lerp.

// this should be run on every frame
// the code sets a position/rotation of the remote player
// get current local time first
var curTime = (new Date()).getTime();
// use an offset to switch it back to around 100/150ms. This is also a common thing google "source multiplayer networking" for example for details.
curTime -= 150;
// find first snapshot which past the curTIme
var firstSnapshot;
// here you look for a first newest snapshot which snaphost.time < curTime
var secondSnapshot;
// you just take a one with (i - 1) from the firstSnapshot;

// you use your lerp function
var player2Posx = lerp(firstSnapshot.x, secondSnapshot.x, curTime - secondSnapshot.time);
// now you apply it to the player


Sorry I didn't realize it takes that much time to describe:)
If you decide to do that and get this far let me know - I'll update the text.


okeoke
Registered User
Quote
2022-07-21 11:42:34

You can use query parameters to send data
yourserver/update?param1=value1&param2=value2


dekon_17
Registered User
Quote
2022-07-21 14:48:19

Woah, okay... This is kinda incredible. I will certainly try this.

Thanks, okeoke!


Create reply:


Posted by: (you are not logged in)


Enter the missing letter in: "Internat?onal" (you are not logged in)


Text:

 

  

Possible Codes


Feature Code
Link [url] www.example.com [/url]
Bold [b]bold text[/b]
Image [img]http://www.example.com/image.jpg[/img]
Quote [quote]quoted text[/quote]
Code [code]source code[/code]

Emoticons


   






Copyright© 2020 Ambiera e.U. all rights reserved.
Privacy Policy | Terms and Conditions | Imprint | Contact