Últimamente he estado ayudando un poco a Esbva un desarrollador indie que está haciendo un juego de batallas multijugador online. Ésto me ha llevado a por fin aprender a crear juegos multijugador con Godot Engine.
Este post no es un tutorial sobre cómo aplicar la API multijugador, si no una pequeña aplicación/ejemplo sobre cómo usarlo. Puedes leer la documentación oficial en este link para conocer los aspectos básicos.
Aunque sinceramente para mí no fue lo suficientemente clara esa documentación, aunque lo intenta, este artículo está también altamente referenciado por el tutorial de narwalengineering.com.
Tal cual se ve en la imagen, una serie de nodos Control, usaremos un TextEdit para presentar el chat (importante activar la propiedad Readonly), y un LineEdit para que el usuario pueda mandar mensajes, estos dos nodos se llaman ChatDisplay y ChatInput respectivamente.
Los botones LeaveButton, JoinButton, HostButton, IpEnter para controlar el acceso y hosting del chat, colocamos por defecto el text de IpEnter con la IP 127.0.0.1 que es el equivalente a la IP local de tu pc.
La función host_room sería la encargada de esto, escribimos lo siguiente:
Para que un cliente se conecte al servidor necesitamos lo siguiente:
Para enviar mensajes usaremos la signal text_entered conectado a send_message.
La función rpc (llamadas de procedimiento remoto) es la forma mas sencilla de realizar la comunicación con el servidor, los parámetros son la función a llamar como string, y luego los parámetros que enviaremos a esa función, en este caso id y msg. Recuerda que cada cliente tiene un id único.
Por último la función receive_message lleva una palabra clave remotesync al inicio, esto es para indicar a Godot que esa función puede ser llamada de forma remota y con el servidor, ésto por razones de seguridad. En el caso de solo necesitar que la función solo sea llamada remotamente podemos usar la keyword remote.
Si quieres probar el chat basta con exportar y abrirlo dos veces, crear el servidor con uno y conectarse con el otro, como se muestra en la imagen.
Si quieres probar conexión local, debes obtener la IP de tu configuración de red, con el comando ipconfig en Windows o ifconfig en Linux puedes ver la información necesaria, yo lo he probado creando el host desde Linux y conectandome desde una PC con Windows y funciona excelente.
Te dejo el proyecto de este chat por si lo quieres ojear: Proyecto en Github.
Puedes descargar el proyecto exportado a las siguientes plataformas:
Windows.
Linux.
Este post no es un tutorial sobre cómo aplicar la API multijugador, si no una pequeña aplicación/ejemplo sobre cómo usarlo. Puedes leer la documentación oficial en este link para conocer los aspectos básicos.
Aunque sinceramente para mí no fue lo suficientemente clara esa documentación, aunque lo intenta, este artículo está también altamente referenciado por el tutorial de narwalengineering.com.
Estructuración del proyecto
Tal cual se ve en la imagen, una serie de nodos Control, usaremos un TextEdit para presentar el chat (importante activar la propiedad Readonly), y un LineEdit para que el usuario pueda mandar mensajes, estos dos nodos se llaman ChatDisplay y ChatInput respectivamente.
Los botones LeaveButton, JoinButton, HostButton, IpEnter para controlar el acceso y hosting del chat, colocamos por defecto el text de IpEnter con la IP 127.0.0.1 que es el equivalente a la IP local de tu pc.
Variables y Señales
extends Control
const PORT = 3000
const MAX_USERS = 4 #not including host
onready var chat_display = $RoomUI/ChatDisplay
onready var chat_input = $RoomUI/ChatInput
func _ready():
chat_input.connect("text_entered", self, "send_message")
get_tree().connect("connected_to_server", self, "enter_room")
get_tree().connect("network_peer_connected", self, "user_entered")
get_tree().connect("network_peer_disconnected", self, "user_exited")
get_tree().connect("server_disconnected", self, "_server_disconnected")
$SetUp/LeaveButton.connect("button_up", self, "leave_room")
$SetUp/JoinButton.connect("button_up", self, "join_room")
$SetUp/HostButton.connect("button_up", self, "host_room")
Creo que queda bastante claro cada señal según su nombre, send_message será para enviar mensajes, enter_room se ejecutará cuando un usuario se conecte al servidor, etc...Inicializando el servidor
La función host_room sería la encargada de esto, escribimos lo siguiente:
func enter_room():
$SetUp/LeaveButton.show()
$SetUp/JoinButton.hide()
$SetUp/IpEnter.hide()
chat_display.text = "Successfully Joined Room\n"
func host_room():
var host = NetworkedMultiplayerENet.new()
host.create_server(PORT, MAX_USERS)
get_tree().set_network_peer(host)
enter_room()
chat_display.text = "Room Created\n"
Para iniciar el servidor debemos crear un objeto NetworkedMultiplayerENet y ejecutar el método create_server con él, luego al árbol de escenas (tree) le pasamos esa red con set_network_peer(), ejecutamos enter_room para adaptar los botones y mostrar en el chat lo sucedido.Conectando al servidor
Para que un cliente se conecte al servidor necesitamos lo siguiente:
func join_room():
var ip = $SetUp/IpEnter.text
var host = NetworkedMultiplayerENet.new()
host.create_client(ip, PORT)
get_tree().set_network_peer(host)
Similar al caso de inicializar el servidor, debemos crear un objeto NetworkedMultiplayerENet, en lugar de create_server, debemos ejecutar create_client y pasar por parámetros la IP del servidor y el puerto de comunicación, luego lo pasamos como parámetro al set_network_peer.Informando la comunicación
func user_entered(id):
chat_display.text += str(id) + " joined the room\n"
func user_exited(id):
chat_display.text += str(id) + " left the room\n"
func _server_disconnected():
chat_display.text += "Disconnected from Server\n"
leave_room()
Las signals que hemos conectado al inicio nos servirán para obtener si alguien se unió, salió o se desconectó del servidor, la id es única por cada usuario conectado, el servidor siempre tendrá el valor 1.Abandonando el servidor
func leave_room():
$SetUp/LeaveButton.hide()
$SetUp/JoinButton.show()
$SetUp/HostButton.show()
$SetUp/IpEnter.show()
chat_display.text += "Left Room\n"
get_tree().set_network_peer(null)
No podemos esperar a que el usuario cierre bruscamente el cliente, debemos permitirle poder dejar la sala, lo único que tenemos que hacer es pasar el parámetro null a set_network_peer, lógicamente después de adaptar los botones para que vuelva a su estado inicial.Enviando y recibiendo mensajes
Para enviar mensajes usaremos la signal text_entered conectado a send_message.
func send_message(msg):
chat_input.text = ""
var id = get_tree().get_network_unique_id()
rpc("receive_message", id, msg)
remotesync func receive_message(id, msg):
chat_display.text += str(id) + ": " + msg + "\n"
La función rpc (llamadas de procedimiento remoto) es la forma mas sencilla de realizar la comunicación con el servidor, los parámetros son la función a llamar como string, y luego los parámetros que enviaremos a esa función, en este caso id y msg. Recuerda que cada cliente tiene un id único.
Por último la función receive_message lleva una palabra clave remotesync al inicio, esto es para indicar a Godot que esa función puede ser llamada de forma remota y con el servidor, ésto por razones de seguridad. En el caso de solo necesitar que la función solo sea llamada remotamente podemos usar la keyword remote.
Si quieres probar el chat basta con exportar y abrirlo dos veces, crear el servidor con uno y conectarse con el otro, como se muestra en la imagen.
Si quieres probar conexión local, debes obtener la IP de tu configuración de red, con el comando ipconfig en Windows o ifconfig en Linux puedes ver la información necesaria, yo lo he probado creando el host desde Linux y conectandome desde una PC con Windows y funciona excelente.
Te dejo el proyecto de este chat por si lo quieres ojear: Proyecto en Github.
Puedes descargar el proyecto exportado a las siguientes plataformas:
Windows.
Linux.
Felicidades por el nuevo Foro men!
ResponderBorrarGracias Iki!
Borrar