Criar um script em tempo real - Amazon GameLift

As traduções são geradas por tradução automática. Em caso de conflito entre o conteúdo da tradução e da versão original em inglês, a versão em inglês prevalecerá.

Criar um script em tempo real

Para usar os servidores em tempo real para o jogo, é preciso fornecer um script (na forma de algum código JavaScript) para configurar e, opcionalmente, personalizar uma frota de servidores em tempo real. Este tópico abrange as principais etapas da criação de um script em tempo real. Assim que o script estiver pronto, faça upload dele no serviço Amazon GameLift e use-o para criar uma frota (consulte Carregar um script de servidores em tempo real no Amazon GameLift).

Para preparar um script para uso com os servidores em tempo real, adicione a seguinte funcionalidade ao script em tempo real.

Gerenciar o ciclo de vida da sessão de jogos (obrigatório)

No mínimo, um script em tempo real deve incluir a função Init(), que prepara o servidor em tempo real para iniciar uma sessão de jogo. Também é altamente recomendável que você também forneça uma maneira de encerrar sessões de jogos, para garantir que novas sessões de jogos possam continuar a ser iniciadas na frota.

A função de retorno de chamada Init(), quando chamada, recebe um objeto de sessão em tempo real, que contém uma interface para o servidor em tempo real. Consulte Interface de servidores em tempo real para obter mais detalhes sobre essa interface.

Para encerrar corretamente a uma sessão de jogo, o script também deve chamar a função session.processEnding em tempo real do servidor. Isso requer um mecanismo para determinar quando encerrar uma sessão. O código do script de exemplo ilustra um mecanismo simples que verifica se há conexões de jogador e aciona o encerramento da sessão de jogo quando nenhum jogador tiver se conectado à sessão por um período especificado.

Os servidores em tempo real com a configuração mais básica – inicialização e encerramento do processo de servidor – atua, essencialmente, como servidores de retransmissão sem estado. O servidor em tempo real retransmite mensagens e dados de jogos entre os clientes de jogos que estão conectados ao jogo, mas não realiza ação independente para processar dados ou executar lógica. Opcionalmente, é possível adicionar a lógica do jogo, acionada por eventos de jogos ou outros mecanismos, conforme necessário para o jogo.

Adicionar lógica do jogo do lado do servidor (opcional)

Opcionalmente, é possível adicionar lógica do jogo ao script em tempo real. Por exemplo, você pode fazer qualquer um ou todos os seguintes. O código de script de exemplo fornece ilustração. Consulte Referência de script de Servidores em Tempo Real do Amazon GameLift.

  • Adicionar lógica orientada por eventos. Implemente as funções de retorno de chamada para responder a eventos de cliente-servidor. Consulte Retornos de chamada de script para servidores em tempo real para obter uma lista completa de retornos de chamada.

  • Acione lógica enviando mensagens ao servidor. Crie um conjunto de códigos de operação especiais para mensagens enviadas de clientes de jogo para o servidor, e adicione funções para manipular o recebimento. Use o retorno de chamada onMessage e analise o conteúdo da mensagem usando a interface gameMessage (consulte gameMessage.opcode).

  • Ative a lógica do jogo para acessar os outros recursos da AWS. Para obter mais detalhes, consulte Comunique-se com outros recursos AWS de suas frotas.

  • Permita que a lógica do jogo acesse as informações da frota da instância em que está sendo executada. Para obter mais detalhes, consulte Obtenha dados da frota para uma instância do Amazon GameLift.

Exemplo de script de servidores em tempo real

Este exemplo ilustra um script básico necessário para implantar o s servidores em tempo real mais alguma lógica personalizada. Ele contém a função Init() necessária, e usa um mecanismo de temporizador para acionar o encerramento da sessão de jogo com base no tempo sem conexões de jogador. Ele também inclui alguns ganchos de lógica personalizada, incluindo algumas implementações de chamada de retorno.

// Example Realtime Server Script 'use strict'; // Example override configuration const configuration = { pingIntervalTime: 30000, maxPlayers: 32 }; // Timing mechanism used to trigger end of game session. Defines how long, in milliseconds, between each tick in the example tick loop const tickTime = 1000; // Defines how to long to wait in Seconds before beginning early termination check in the example tick loop const minimumElapsedTime = 120; var session; // The Realtime server session object var logger; // Log at appropriate level via .info(), .warn(), .error(), .debug() var startTime; // Records the time the process started var activePlayers = 0; // Records the number of connected players var onProcessStartedCalled = false; // Record if onProcessStarted has been called // Example custom op codes for user-defined messages // Any positive op code number can be defined here. These should match your client code. const OP_CODE_CUSTOM_OP1 = 111; const OP_CODE_CUSTOM_OP1_REPLY = 112; const OP_CODE_PLAYER_ACCEPTED = 113; const OP_CODE_DISCONNECT_NOTIFICATION = 114; // Example groups for user-defined groups // Any positive group number can be defined here. These should match your client code. // When referring to user-defined groups, "-1" represents all groups, "0" is reserved. const RED_TEAM_GROUP = 1; const BLUE_TEAM_GROUP = 2; // Called when game server is initialized, passed server's object of current session function init(rtSession) { session = rtSession; logger = session.getLogger(); } // On Process Started is called when the process has begun and we need to perform any // bootstrapping. This is where the developer should insert any code to prepare // the process to be able to host a game session, for example load some settings or set state // // Return true if the process has been appropriately prepared and it is okay to invoke the // GameLift ProcessReady() call. function onProcessStarted(args) { onProcessStartedCalled = true; logger.info("Starting process with args: " + args); logger.info("Ready to host games..."); return true; } // Called when a new game session is started on the process function onStartGameSession(gameSession) { // Complete any game session set-up // Set up an example tick loop to perform server initiated actions startTime = getTimeInS(); tickLoop(); } // Handle process termination if the process is being terminated by GameLift // You do not need to call ProcessEnding here function onProcessTerminate() { // Perform any clean up } // Return true if the process is healthy function onHealthCheck() { return true; } // On Player Connect is called when a player has passed initial validation // Return true if player should connect, false to reject function onPlayerConnect(connectMsg) { // Perform any validation needed for connectMsg.payload, connectMsg.peerId return true; } // Called when a Player is accepted into the game function onPlayerAccepted(player) { // This player was accepted -- let's send them a message const msg = session.newTextGameMessage(OP_CODE_PLAYER_ACCEPTED, player.peerId, "Peer " + player.peerId + " accepted"); session.sendReliableMessage(msg, player.peerId); activePlayers++; } // On Player Disconnect is called when a player has left or been forcibly terminated // Is only called for players that actually connected to the server and not those rejected by validation // This is called before the player is removed from the player list function onPlayerDisconnect(peerId) { // send a message to each remaining player letting them know about the disconnect const outMessage = session.newTextGameMessage(OP_CODE_DISCONNECT_NOTIFICATION, session.getServerId(), "Peer " + peerId + " disconnected"); session.getPlayers().forEach((player, playerId) => { if (playerId != peerId) { session.sendReliableMessage(outMessage, playerId); } }); activePlayers--; } // Handle a message to the server function onMessage(gameMessage) { switch (gameMessage.opCode) { case OP_CODE_CUSTOM_OP1: { // do operation 1 with gameMessage.payload for example sendToGroup const outMessage = session.newTextGameMessage(OP_CODE_CUSTOM_OP1_REPLY, session.getServerId(), gameMessage.payload); session.sendGroupMessage(outMessage, RED_TEAM_GROUP); break; } } } // Return true if the send should be allowed function onSendToPlayer(gameMessage) { // This example rejects any payloads containing "Reject" return (!gameMessage.getPayloadAsText().includes("Reject")); } // Return true if the send to group should be allowed // Use gameMessage.getPayloadAsText() to get the message contents function onSendToGroup(gameMessage) { return true; } // Return true if the player is allowed to join the group function onPlayerJoinGroup(groupId, peerId) { return true; } // Return true if the player is allowed to leave the group function onPlayerLeaveGroup(groupId, peerId) { return true; } // A simple tick loop example // Checks to see if a minimum amount of time has passed before seeing if the game has ended async function tickLoop() { const elapsedTime = getTimeInS() - startTime; logger.info("Tick... " + elapsedTime + " activePlayers: " + activePlayers); // In Tick loop - see if all players have left early after a minimum period of time has passed // Call processEnding() to terminate the process and quit if ( (activePlayers == 0) && (elapsedTime > minimumElapsedTime)) { logger.info("All players disconnected. Ending game"); const outcome = await session.processEnding(); logger.info("Completed process ending with: " + outcome); process.exit(0); } else { setTimeout(tickLoop, tickTime); } } // Calculates the current time in seconds function getTimeInS() { return Math.round(new Date().getTime()/1000); } exports.ssExports = { configuration: configuration, init: init, onProcessStarted: onProcessStarted, onMessage: onMessage, onPlayerConnect: onPlayerConnect, onPlayerAccepted: onPlayerAccepted, onPlayerDisconnect: onPlayerDisconnect, onSendToPlayer: onSendToPlayer, onSendToGroup: onSendToGroup, onPlayerJoinGroup: onPlayerJoinGroup, onPlayerLeaveGroup: onPlayerLeaveGroup, onStartGameSession: onStartGameSession, onProcessTerminate: onProcessTerminate, onHealthCheck: onHealthCheck };