Os jogadores agora podem coletar moedas e perdê-las quando morrem, mas as moedas não fazem nada, e a maior parte do mundo 3D é inacessível sem a capacidade de pular muito alto. Esta seção do tutorial ensina como finalizar a lógica do seu jogo adicionando um botão na tela que gasta moedas para aumentar o poder de pulo.
Criar o botão de upgrade
Interfaces 2D no Roblox são tipicamente compostas por uma coleção de componentes de GUI dentro de um contêiner de GUI. Neste caso, você só precisa de um componente TextButton que diz Upgrade Jump (5 Moedas) dentro de um contêiner ScreenGui.
No ReplicatedStorage, crie uma pasta chamada Instances.
Dentro da pasta Instances, crie um ScreenGui chamado JumpPurchaseGui com ResetOnSpawn desativado.
Dentro do JumpPurchaseGui, crie um TextButton chamado JumpButton com as seguintes propriedades:
- Text: "Upgrade Jump (5 Moedas)"
- TextSize: 25
- AnchorPoint: 1, 1
- Position: {1, 0}, {1, 0}
Também dentro da pasta Instances, crie uma RemoteFunction chamada IncreaseJumpPowerFunction.
Finalmente, no serviço StarterPlayer, ative a propriedade CharacterUseJumpPower.Definir dados de poder de pulo
Atualmente, apenas a contagem de moedas é armazenada para cada jogador no script de módulo PlayerData. Você também precisa armazenar e atualizar o poder de pulo da mesma forma. Como as funções em PlayerData não são específicas para os dados que estão sendo alterados, tudo o que é necessário para armazenar o poder de pulo do jogador é adicionar uma chave Jump e inicializar seu valor inicial em defaultPlayerData().
No ServerStorage, substitua o código existente do módulo PlayerData pelo seguinte:
```lua
local PlayerData = {}
PlayerData.COIN_KEY_NAME = "Coins"
PlayerData.JUMP_KEY_NAME = "Jump"
local playerData = {
--[[
[userId: string] = {
["Coins"] = coinAmount: number,
["Jump"] = jumpPower: number
}
--]]
}
local function defaultPlayerData()
return {
[PlayerData.COIN_KEY_NAME] = 0,
[PlayerData.JUMP_KEY_NAME] = 0,
}
end
local function getData(player)
local data = playerData[tostring(player.UserId)] or defaultPlayerData()
playerData[tostring(player.UserId)] = data
return data
end
function PlayerData.getValue(player, key)
return getData(player)[key]
end
function PlayerData.updateValue(player, key, updateFunction)
local data = getData(player)
local oldValue = data[key]
local newValue = updateFunction(oldValue)
data[key] = newValue
return newValue
end
return PlayerData
```Atualizar dados de poder de pulo
Agora que PlayerData é capaz de rastrear o poder de pulo, você precisa implementar a lógica no servidor para atualizar o poder de pulo a partir de uma solicitação do cliente do jogador.
O servidor e o cliente podem se comunicar através de RemoteEvents ou RemoteFunctions. Eventos remotos não aguardam quando são disparados e podem ser usados para comunicação unidirecional. Funções remotas, por outro lado, aguardam até receber uma resposta, o que permite comunicação bidirecional.
Para este tutorial, o cliente precisa saber se o servidor atualizou o poder de pulo do jogador com sucesso, então você deve usar uma função remota.
No ServerScriptService, crie um Script chamado JumpService com o seguinte código:
```lua
-- Serviços
local ReplicatedStorage = game:GetService("ReplicatedStorage")
local ServerStorage = game:GetService("ServerStorage")
local Players = game:GetService("Players")
-- Módulos
local Leaderboard = require(ServerStorage.Leaderboard)
local PlayerData = require(ServerStorage.PlayerData)
-- Eventos
local IncreaseJumpPowerFunction = ReplicatedStorage.Instances.IncreaseJumpPowerFunction
local JUMP_KEY_NAME = PlayerData.JUMP_KEY_NAME
local COIN_KEY_NAME = PlayerData.COIN_KEY_NAME
local JUMP_POWER_INCREMENT = 30
local JUMP_COIN_COST = 5
local function updateJumpPower(player, updateFunction)
-- Atualiza a tabela de poder de pulo
local newJumpPower = PlayerData.updateValue(player, JUMP_KEY_NAME, updateFunction)
-- Atualiza o poder de pulo dos jogadores
local character = player.Character or player.CharacterAdded:Wait()
local humanoid = character:FindFirstChildWhichIsA("Humanoid")
if humanoid then
humanoid.JumpPower = newJumpPower
-- Atualiza o leaderboard de pulo
Leaderboard.setStat(player, JUMP_KEY_NAME, newJumpPower)
end
end
local function onPurchaseJumpIncrease(player)
local coinAmount = PlayerData.getValue(player, COIN_KEY_NAME)
if coinAmount < JUMP_COIN_COST then
return false
end
-- Aumenta o poder de pulo do jogador
updateJumpPower(player, function(oldJumpPower)
oldJumpPower = oldJumpPower or 0
return oldJumpPower + JUMP_POWER_INCREMENT
end)
-- Atualiza a tabela de moedas
local newCoinAmount = PlayerData.updateValue(player, COIN_KEY_NAME, function(oldCoinAmount)
return oldCoinAmount - JUMP_COIN_COST
end)
-- Atualiza o leaderboard de moedas
Leaderboard.setStat(player, COIN_KEY_NAME, newCoinAmount)
return true
end
local function onCharacterAdded(player)
-- Redefine o poder de pulo do jogador quando o personagem é adicionado
updateJumpPower(player, function(_)
return 0
end)
end
-- Inicializa qualquer jogador adicionado antes de conectar ao evento PlayerAdded
for _, player in Players:GetPlayers() do
onCharacterAdded(player)
end
-- Inicialização normal dos jogadores a partir do evento PlayerAdded
local function onPlayerAdded(player)
player.CharacterAdded:Connect(function()
onCharacterAdded(player)
end)
end
local function onPlayerRemoved(player)
updateJumpPower(player, function(_)
return nil
end)
end
IncreaseJumpPowerFunction.OnServerInvoke = onPurchaseJumpIncrease
Players.PlayerAdded:Connect(onPlayerAdded)
Players.PlayerRemoving:Connect(onPlayerRemoved)
```As seções a seguir descrevem o código em mais detalhes.
Atualizar os dados de poder de pulo - updateJumpPower() atualiza o poder de pulo do jogador e o leaderboard para fornecer feedback visual. Esta função se assemelha ao código que danifica jogadores em Criar perigos para jogadores. Desde que um modelo Character e Humanoid existam para o jogador que está sendo atualizado, a função atualiza a propriedade JumpPower para o novo valor armazenado por PlayerData, aumentando-o em 30. Se você quiser que seu jogo dure um pouco mais, pode diminuir esse número.
Validar solicitações do servidor - onPurchaseJumpIncrease() primeiro verifica se o jogador realmente tem o número de moedas necessárias para comprar o upgrade. Todas as solicitações de clientes para o servidor devem ser validadas para evitar que agentes mal-intencionados enviem solicitações falsas e explorem seu jogo.
Adicionar o botão à GUI do jogador
Um objeto ScreenGui só é exibido na tela se estiver parentado ao objeto PlayerGui de um jogador. Por padrão, isso contém a GUI do sistema, como a janela de chat. Agora você precisa criar um script no ReplicatedStorage para copiar o botão de upgrade na GUI de cada jogador e implementar o comportamento para quando o botão for pressionado.
No ReplicatedStorage, crie um Script chamado JumpButtonClickHandler com RunContext definido como Client e o seguinte código:
```lua
local ReplicatedStorage = game:GetService("ReplicatedStorage")
local Players = game:GetService("Players")
local player = Players.LocalPlayer
local playerGui = player.PlayerGui
local IncreaseJumpPowerFunction = ReplicatedStorage.Instances.IncreaseJumpPowerFunction
local jumpPurchaseGui = ReplicatedStorage.Instances.JumpPurchaseGui
local jumpButton = jumpPurchaseGui.JumpButton
local function onButtonClicked()
local success, purchased = pcall(IncreaseJumpPowerFunction.InvokeServer, IncreaseJumpPowerFunction)
if not success then
-- purchased será a mensagem de erro se success for falso
error(purchased)
elseif success and not purchased then
warn("Moedas insuficientes!")
end
end
jumpButton.Activated:Connect(onButtonClicked)
-- Adiciona o JumpPurchaseGui à GUI do jogador
jumpPurchaseGui.Parent = playerGui
```As seções a seguir descrevem o código em mais detalhes.
- Obter referências à GUI e à função do servidor - As variáveis IncreaseJumpPowerFunction, jumpPurchaseGui e jumpButton contêm referências à função e à GUI que chama a função que você precisará mais tarde.
- Definir o manipulador de eventos - onButtonClicked() define a lógica para quando os usuários clicam no botão de upgrade. Ele usa pcall() (chamada protegida) para invocar a RemoteFunction. Qualquer comunicação cliente-servidor como esta requer pcall() para lidar com erros ou problemas de conexão.
- Conectar o manipulador ao botão - O evento Activated é compatível em todas as plataformas, incluindo mouse, tela sensível ao toque ou contextos de controle. Ele é acionado quando um clique, toque ou botão do controle é liberado.
Testar
Selecione Testar no menu suspenso e clique em Jogar. O botão Upgrade Jump aparece no canto inferior direito.
Tente clicar no botão antes de coletar quaisquer moedas para verificar se ele não lhe concede poder de pulo adicional, depois tente coletar algumas moedas e veja se o upgrade funciona quando você clica novamente.
Com o código completo, tente ajustar a dificuldade: adicione moedas se o ritmo parecer lento, ou remova algumas e esconda-as em lugares mais difíceis se os upgrades forem muito fáceis.