Skip to main content

Indie game storeFree gamesFun gamesHorror games
Game developmentAssetsComics
SalesBundles
Jobs
TagsGame Engines

banddans

20
Posts
2
Followers
A member registered Apr 16, 2023 · View creator page →

Creator of

Recent community posts

Cool! Is there unity frameworks or do you have to run python from unity or how do you do this?

Is the AI just a recording or does it run in realtime in my browser?

Yep!

Also make sure to put that node into your player and some code that spawns players when they join.

It's not C# its javascript, which vscode handles very well too ;) And the javascript just starts a server so just make it keep running and then run your cool project with the signaling code and the web rtc stuff and you'll get a multiplayer connection after a second or two.

The signaling server should not be pasted into godot but into vscode or  anything and the run it on a raspberry pi or anything, the project don't work without it.

This is my multiplayer tree.

Some code for WebRTC if you wanna learn:


Signaling server (js):

import WebSocket, { WebSocketServer } from "ws";

const wss = new WebSocketServer({ port: 9396 });

const messages = {
ASSIGN_ID: 0,
JOIN_LOBBY: 1,
PLAYERS_FOUND: 2,
SEND_ICE_CANDIDATE: 3,
SEND_DESCRIPTION: 4,
RECEIVE_ICE_CANDIDATE: 5,
RECEIVE_DESCRIPTION: 6,

};

let players = {};

let waiting_players = [];

let waiting_player_ids = [];

let next_player_id = 2;

const PLAYERS_IN_GAME = 3;

wss.on("connection", function connection(ws) {
const player_id = next_player_id;
players[player_id] = ws;
next_player_id += 1;

ws.on("close", function close() {
delete players[player_id];
console.log("Player left :(");
});

ws.on("error", console.error);

ws.on("message", function message(data) {
try {
const json_data = JSON.parse(data);
console.log(JSON.stringify(json_data));
if (json_data.message == messages.JOIN_LOBBY) {
console.log("Player wants to join lobby.");
waiting_players.push(ws);
waiting_player_ids.push(player_id);
if (waiting_players.length >= PLAYERS_IN_GAME) {
console.log("Lobby found!");
console.log(waiting_players);
/*
let lowest_id = -1;
for (let i = 0; i < PLAYERS_IN_GAME; i++) {
if (waiting_player_ids[i] < lowest_id || lowest_id == -1) {
lowest_id = waiting_player_ids[i];
}
}
for (let i = 0; i < PLAYERS_IN_GAME; i++) {
if (waiting_player_ids[i] == lowest_id) {
waiting_player_ids[i] = 1;
}
}
*/
for (let i = 0; i < PLAYERS_IN_GAME; i++) {
console.log(waiting_players[i]);
waiting_players[i].send(
JSON.stringify({
message: messages.PLAYERS_FOUND,
players: waiting_player_ids,
})
);
}
waiting_players = [];
waiting_player_ids = [];
}
}
if (json_data.message == messages.SEND_ICE_CANDIDATE) {
players[json_data.target].send(
JSON.stringify({
message: messages.RECEIVE_ICE_CANDIDATE,
from: player_id,
mid_name: json_data.mid_name,
index_name: json_data.index_name,
sdp_name: json_data.sdp_name,
})
);
}
if (json_data.message == messages.SEND_DESCRIPTION) {
console.log(json_data);
players[json_data.target].send(
JSON.stringify({
message: messages.RECEIVE_DESCRIPTION,
from: player_id,
data: json_data.data,
type: json_data.type,
})
);
}
} catch (e) {
console.log('Got strange data: "' + data + '"');
console.error(e);
}
});
ws.send(JSON.stringify({ message: messages.ASSIGN_ID, id: player_id }));

});






Client signaling (gdscript):

extends Node

class_name Signaling

@onready var web_rtc_manager : WebRTCManager = $"../WebRTC"

@onready var network_manager : NetworkManager = get_parent()

var socket = WebSocketPeer.new()

var waiting_for_join_request : bool = false

var my_id : int

var is_host : bool

var host_id : int = -1

enum messages {

ASSIGN_ID,

JOIN_LOBBY,

PLAYERS_FOUND,

SEND_ICE_CANDIDATE,

SEND_DESCRIPTION,

RECEIVE_ICE_CANDIDATE,

RECEIVE_DESCRIPTION,

}

func _ready():

socket.connect_to_url("ws://localhost:9396")

waiting_for_join_request = true

func _process(_delta):

socket.poll()

var state = socket.get_ready_state()

if state == WebSocketPeer.STATE_OPEN:

if waiting_for_join_request:

socket.send_text(JSON.stringify({"message":messages.JOIN_LOBBY}))

waiting_for_join_request = false

while socket.get_available_packet_count():

var packet_data : Dictionary = JSON.parse_string(socket.get_packet().get_string_from_utf8())

if packet_data.message == messages.ASSIGN_ID:

my_id = packet_data.id

web_rtc_manager.my_id = my_id

network_manager.id = my_id

web_rtc_manager.connected(my_id)

elif packet_data.message == messages.PLAYERS_FOUND:

web_rtc_manager.players_in_game = len(packet_data.players)

is_host = true

for player_id : int in packet_data.players:

web_rtc_manager.connect_to_player(player_id)

if player_id > my_id:

is_host = false

if player_id < host_id or host_id == -1:

host_id = player_id

network_manager.is_host = is_host

network_manager.host_id = host_id

print(packet_data.players)

print("Found players!")

elif packet_data.message == messages.RECEIVE_ICE_CANDIDATE:

web_rtc_manager.add_ice_candidate(packet_data.mid_name, packet_data.index_name, packet_data.sdp_name, packet_data.from)

elif packet_data.message == messages.RECEIVE_DESCRIPTION:

web_rtc_manager.set_remote_description(packet_data.type, packet_data.data, packet_data.from)

elif state == WebSocketPeer.STATE_CLOSING:

# Keep polling to achieve proper close.

pass

elif state == WebSocketPeer.STATE_CLOSED:

var code = socket.get_close_code()

var reason = socket.get_close_reason()

print("WebSocket closed with code: %d, reason %s. Clean: %s" % [code, reason, code != -1])

set_process(false) # Stop processing.

func send(message : messages, data : Dictionary, target : int):

data["message"] = message

data["target"] = target

socket.send_text(JSON.stringify(data))

func send_description(type : String, data : String, target : int):

send(messages.SEND_DESCRIPTION, {"data": data, "type": type}, target)

func send_ice_candidate(mid_name, index_name, sdp_name, target : int):

send(messages.SEND_ICE_CANDIDATE, {"mid_name":mid_name, "index_name":index_name, "sdp_name":sdp_name}, target)






WebRTC manager (gdscript):

extends Node

class_name WebRTCManager

@onready var signaling : Signaling = $"../Signaling"

var peer : WebRTCMultiplayerPeer = WebRTCMultiplayerPeer.new()

var my_id : int

var players_in_game : int

var connected_peers : int = 0

func _ready():

multiplayer.peer_connected.connect(peer_connected)

func connect_to_player(id : int):

var player_peer : WebRTCPeerConnection = WebRTCPeerConnection.new()

player_peer.initialize({

"iceServers" : [{ "urls": ["stun:stun.l.google.com:19302"] }]

})

player_peer.session_description_created.connect(offer_created.bind(id))

player_peer.ice_candidate_created.connect(ice_candidate_created.bind(id))

peer.add_peer(player_peer, id)

if id < my_id:

player_peer.create_offer()

func offer_created(type : String, data : String, id : int):

signaling.send_description(type, data, id)

func ice_candidate_created(mid_name, index_name, sdp_name, id : int):

signaling.send_ice_candidate(mid_name, index_name, sdp_name, id)

func add_ice_candidate(mid_name, index_name, sdp_name, id : int):

peer.get_peer(id).connection.add_ice_candidate(mid_name, index_name, sdp_name)

func set_remote_description(type : String, data : String, id : int):

peer.get_peer(id).connection.set_remote_description(type, data)

func connected(id):

peer.create_mesh(id)

multiplayer.multiplayer_peer = peer

func peer_connected(id):

print("Connection with " + str(id))

connected_peers += 1

if connected_peers == players_in_game - 1:

get_parent().connected_to_everyone()

@rpc("any_peer", "call_local")

func ping():

print("I got pinged!")

func _on_ping_button_pressed():

ping.rpc()


Yes, it's kinda complicated but it works.

Online would be cool :D Do you know about WebRTC?

Really like it! These moving platforms deserve more work though...

1. Players are rigidbodies

2. Quicksand, https://fonts.google.com/specimen/Quicksand?query=quicksand

3. I change the scene

Wanna play an unlisted game tommorow, its online? Ima go sleep now but i can give you a link then.

Yeah im on scratch too.

Just start digging.

Why not? Can't you change framerate somewhere?

Okay, but can you still add higher framerate in the export? Like 30 or 60 fps?

Really cool though :D

(1 edit)

They are looking much smoother in the previews than when i uploaded them in godot, why?

lurn moment

Play on scratch if you want the leaderboard:

https://scratch.mit.edu/projects/404659699/