Close
    Search Search

    Tutorial: Como fazer um jogo de plataforma 2D

    Página do tutorial; este artigo é um tutorial intermediário.Todos os tutoriais · Tutoriais de script

    No último tutorial, cobrimos como fazer um pacote de saúde no Roblox. Neste tutorial, abordaremos a obtenção de dados do jogador e a personalização dos controles do personagem. Para fazer isso, faremos uma câmera simples e um sistema de controle para um jogo de plataforma 2D.

    Conteúdo

    Instâncias necessárias

    • Tutorial: Como fazer um jogo de plataforma 2DTutorial: Como fazer um jogo de plataforma 2D Área de trabalho
      • Tutorial: Como fazer um jogo de plataforma 2D Câmera
      • Tutorial: Como fazer um jogo de plataforma 2DTutorial: Como fazer um jogo de plataforma 2D seu nome
    • Tutorial: Como fazer um jogo de plataforma 2DTutorial: Como fazer um jogo de plataforma 2D Jogadores
      • Tutorial: Como fazer um jogo de plataforma 2DTutorial: Como fazer um jogo de plataforma 2D seu nome
    • Tutorial: Como fazer um jogo de plataforma 2DTutorial: Como fazer um jogo de plataforma 2D StarterPlayer
      • Tutorial: Como fazer um jogo de plataforma 2DTutorial: Como fazer um jogo de plataforma 2D StarterPlayerScripts
        • Tutorial: Como fazer um jogo de plataforma 2D CameraScript
        • Tutorial: Como fazer um jogo de plataforma 2D ControlScript
    • Tutorial: Como fazer um jogo de plataforma 2D ContextActionService
    • Tutorial: Como fazer um jogo de plataforma 2D RunService

    tutorial

    Tutorial: Como fazer um jogo de plataforma 2D



    Antes de entrarmos no código real do jogo de plataforma, é importante entender como os jogos Roblox são estruturados. Quando um jogo Roblox é inicializado, um servidor Roblox inicia uma cópia do jogo. Esta cópia do jogo é chamada de servidor. Este servidor é responsável por manter o controle de todas as peças e jogadores no jogo. Quando um jogador entra no jogo, ele também executa uma cópia em sua máquina local; A versão do jogador do mundo do jogo é chamada de Cliente.



    Sempre que é feita alguma alteração no Servidor, como a movimentação de uma peça, esta informação é enviada a todos os Clientes de forma automática. o Scripts que temos usado até agora executado exclusivamente no servidor. Isso funciona quando precisamos executar um código que afeta o servidor, mas e a câmera e a entrada? Essas são coisas que afetam jogadores individuais, mas não o servidor. Para escrever código para jogadores individuais, precisamos usar um LocalScript. Este é um tipo especial de script executado na máquina do Cliente, não no servidor.

    Câmera

    Existem vários estilos de câmeras para jogos 2D, mas o que usaremos é muito simples: se o jogador se mover muito para a direita da câmera, a câmera se moverá para a direita. Caso contrário, a câmera permanece parada.

    instalação

    A primeira coisa a configurar será a própria câmera. Precisamos sobrescrever o script de câmera padrão do Roblox para escrever o nosso. Para fazer isso, insira um LocalScript para dentro StarterPlayerScripts e renomeie-o como CameraScript.

    Agora precisamos inicializar onde a câmera começa.

    local cameraHeight = 12 local cameraZOffset = 20 local camera = game.Workspace.CurrentCamera local player = game.Players.LocalPlayer local function setupCamera () camera.CFrame = CFrame.new (Vector3.new (0, cameraHeight, cameraZOffset), Vector3. new (0, cameraHeight, 0)) end setupCamera () player.CharacterAdded: connect (setupCamera)

    Primeiro, configuramos variáveis ​​para a altura da câmera, bem como a distância que queremos que ela esteja do plano em que o jogador está caminhando. Colocamos essas variáveis ​​no topo para torná-las fáceis de encontrar, caso seja necessário ajustá-las posteriormente.


    Em seguida, obtemos variáveis ​​para a câmera e o jogador. Em um LocalScript, game.Workspace.CurrentCamera retorna a câmera do player local e game.Players.LocalPlayer obtém o player local.


    A seguir, criamos uma função para definir a posição inicial da câmera. Precisaremos disso quando o jogador entrar no jogo pela primeira vez, bem como sempre que seu personagem reaparecer. Nesta função, simplesmente configuramos o CFrame da câmera.

    Um CFrame (abreviação de CoordinateFrame) armazena a posição de um objeto e sua orientação. Você costuma vê-los usados ​​para manipular partes, mas a câmera de um jogador também tem um CFrame. Embora existam várias maneiras de fazer um CFrame, usaremos a função .new de CFrame que recebe dois Vector3 como argumentos. O primeiro Vector3 determina a posição do CFrame. O segundo Vector3 define para onde o CFrame está apontando.

    Chamamos nossa função imediatamente após declará-la, para que a câmera seja colocada na posição correta assim que o jogador entrar. Também vinculamos nossa função ao evento CharacterAdded do jogador para que seja chamada sempre que o personagem do jogador reaparece.

    Movendo a câmera

    Agora precisamos mover a câmera conforme o personagem do jogador se move para a direita. Ao lidar com câmeras em movimento, é importante entender como a renderização funciona no Roblox. A câmera define exatamente onde na cena 3D queremos que o jogador veja, o que então determina o que é renderizado na tela. O mecanismo Roblox atualiza essa renderização a cada 1/60 de segundo; Renderizar isso rapidamente significa que o visualizador vê uma transição suave entre os quadros. Para garantir que a câmera se mova suavemente, precisamos nos certificar de que a posição da câmera seja atualizada sempre que ocorrer a atualização da renderização. Felizmente, isso é muito fácil com uma função chamada BindToRenderStep.


    cameraHeight local = 12 camera localZOffset = 20 cameraXChase local = 10 cameraSpeed ​​local = .25 camera local = game.Workspace.CurrentCamera local player = game.Players.LocalPlayer local RunService = game: GetService ('RunService') função local setupCamera () camera .CFrame = CFrame.new (Vector3.new (0, cameraHeight, cameraZOffset), Vector3.new (0, cameraHeight, 0)) end setupCamera () player.CharacterAdded: conectar (setupCamera) função local onUpdate () se player.Character e player.Character: FindFirstChild ('Torso') e depois playerX local = player.Character.Torso.Position.X local cameraX = camera.CFrame.pX se cameraX - cameraXChase <playerX then camera.CFrame = camera.CFrame + Vector3.new (cameraSpeed, 0, 0) end end end RunService: BindToRenderStep ('Camera', Enum.RenderPriority.Camera.Value, onUpdate)

    Estamos fazendo algumas coisas aqui, então vamos examiná-las uma de cada vez. Primeiro, declaramos mais algumas variáveis. O primeiro, cameraXChase, representa a distância que o jogador pode estar da câmera na dimensão X antes que a câmera comece a se mover. cameraSpeed ​​é o quão longe a câmera se moverá a cada etapa de renderização para tentar alcançar o jogador.


    A próxima variável que declaramos é para RunService que só precisamos para o seu BindToRenderStep função. Pulando para o final do script, observe que chamamos BindToRenderStep com três valores. O primeiro é um nome para essa vinculação, o segundo é quando durante a etapa de renderização para executar e, por último, a função que queremos vincular - neste caso, nossa função personalizada, onUpdate.

    onUpdate faz algumas coisas. Primeiro, ele verifica se o jogador tem um modelo de personagem e se esse modelo tem uma parte chamada Torso. Se não tivesse essas coisas, o jogador provavelmente está desovando ou saindo do jogo. Em qualquer um desses casos, não precisamos realmente da câmera para fazer nada. Mas se o jogador tem um personagem, então obtemos a posição X do personagem e a posição X da câmera. Em seguida, verificamos a que distância o personagem está da câmera. Se o personagem estiver muito perto da câmera, atualizamos o CFrame da câmera à direita.

    Tutorial: Como fazer um jogo de plataforma 2D

    Neste caso, a câmera não deve se mover.

    Tutorial: Como fazer um jogo de plataforma 2D

    Nesse caso, a câmera deve se mover.

    controles

    Agora que a câmera está travada na vista lateral, vamos adicionar controles personalizados para mover o personagem apenas no plano XY. Este código lidará com a entrada, então ele precisará ir para um LocalScript. Insira outro LocalScript em StarterPlayerScripts e renomeie-o para ControlScript. Assim como a inserção de um LocalScript chamado CameraScript sobrescreve os controles padrão da câmera, o ControlScript sobrescreve os controles de caracteres padrão.

    Binding Controls

    Em nosso LocalScript, precisaremos criar várias funções e vinculá-las à entrada do player. Existem algumas maneiras de fazer isso, mas uma das mais convenientes é usar ContextActionService. Este serviço permite vincular várias fontes de entrada a uma única função. Isso é muito útil se você quiser que seu jogo lide com os vários dispositivos de entrada que o Roblox suporta (teclado, touchscreen, gamepad, etc).

    Antes de escrevermos o código que realmente move o personagem do jogador, vamos primeiro configurar as ligações de controle. Em nosso novo LocalScript, adicione o seguinte:

    local player = game.Players.LocalPlayer local RunService = game: GetService ('RunService') local ContextActionService = game: GetService ('ContextActionService') local function onLeft (actionName, inputState) end local function onRight (actionName, inputState) end local function onJump (actionName, inputState) end local function onUpdate () end RunService: BindToRenderStep ('Control', Enum.RenderPriority.Input.Value, onUpdate) ContextActionService: BindAction ('Left', onLeft, true, 'a', Enum.KeyCode .Left, Enum.KeyCode.DPadLeft) ContextActionService: BindAction ('Right', onRight, true, 'd', Enum.KeyCode.Right, Enum.KeyCode.DPadRight) ContextActionService: BindAction ('Jump', onJump, true, ' w ', Enum.KeyCode.Space, Enum.KeyCode.Up, Enum.KeyCode.DPadUp, Enum.KeyCode.ButtonA)

    Assim como em nosso CameraScript, estamos criando variáveis ​​para o jogador e para RunService. Também precisamos de uma variável para ContextActionService. Em seguida, criamos uma função para cada ação que o jogador pode realizar em nosso jogo: onLeft, onRight e onJump. Essas funções aceitam dois argumentos: o nome da ação e o estado da entrada que chamou a função.


    ⚠️AvisoMesmo que usaremos apenas o parâmetro inputState para as funções de entrada, ainda precisamos incluir o nome da ação como o primeiro parâmetro, pois o evento que chama essas funções incluirá ambos. Por exemplo, considere o seguinte código:

    função local test1 (a, b) print (b) end local function test2 (b) print (b) end test1 ("dog", "cat") test2 ("dog", "cat") Se quisermos a função que imprime cat, neste caso, precisaríamos usar test1, pois cat é passado como o segundo parâmetro.


    Como no CameraScript, também criamos uma função de atualização que vinculamos a RenderStepped. Esta função realmente fará a movimentação do personagem depois de manipularmos a entrada. Certifique-se de que a prioridade da ligação esteja definida como Entrada (usamos a Câmera antes).

    Em seguida, vinculamos nossas três funções de entrada usando BindAction. BindAction leva vários argumentos. O primeiro é o nome da ação. A segunda é a função que você deseja vincular. O terceiro argumento é se você deseja criar automaticamente um botão para essa ação em dispositivos de toque, como telefones e tablets. Por último, você pode incluir uma lista de entradas com as quais deseja acionar a ação. Se a entrada for apenas uma tecla de letra no teclado, você pode incluí-la como uma string entre aspas (""). Caso contrário, você pode usar Enum.KeyCode para especificar teclas e botões especiais.

    Movendo o personagem

    Agora vamos adicionar o código para mover o personagem. Novamente, vamos fazer o movimento real na função onUpdate. Todas as funções de entrada definirão variáveis ​​que onUpdate usará para determinar como mover o caractere.

    local player = game.Players.LocalPlayer local RunService = game: GetService ('RunService') local ContextActionService = game: GetService ('ContextActionService') local jumping = false local leftValue, rightValue = 0, 0 função local onLeft (actionName, inputState) if inputState == Enum.UserInputState.Begin then leftValue = 1 elseif inputState == Enum.UserInputState.End then leftValue = 0 end end local function onRight (actionName, inputState) if inputState == Enum.UserInputState.Begin then rightValue = 1 elseif inputState == Enum.UserInputState.End then rightValue = 0 finalizar a função local onJump (actionName, inputState) if inputState == Enum.UserInputState.Begin then jumping = true elseif inputState == Enum.UserInputState.End then jumping = false finalizar função local onUpdate () se player.Character e player.Character: FindFirstChild ('Humanoid') então se pulando player.Character.Humanoid.Jump = true end local moveDirection = rightValue - leftValue player.Character.Humanoid: Move (Vector 3.new (moveDirection, 0,0), false) end end RunService: BindToRenderStep ('Control', Enum.RenderPriority.Input.Value, onUpdate) ContextActionService: BindAction ('Left', onLeft, true, 'a', Enum .KeyCode.Left, Enum.KeyCode.DPadLeft) ContextActionService: BindAction ('Right', onRight, true, 'd', Enum.KeyCode.Right, Enum.KeyCode.DPadRight) ContextActionService: BindAction ('Jump', onJump, true , 'w', Enum.KeyCode.Space, Enum.KeyCode.Up, Enum.KeyCode.DPadUp, Enum.KeyCode.ButtonA)

    Primeiro configuramos três novas variáveis: jumping, leftValue e rightValue. jumping é apenas um booleano: o jogador vai saltar ou não. Esquerda e direita são um pouco mais complicadas. Quando o jogador segura a esquerda, o personagem obviamente deve se mover para a esquerda, mas quando o jogador pressiona a direita enquanto a esquerda é mantida pressionada, o personagem deve parar. Se o jogador soltar para a esquerda ou para a direita, o personagem deve se mover na direção da tecla que ainda está sendo pressionada. Criar uma variável para cada direção será útil, como você verá na função onUpdate.


    ⚠️AvisoVocê deve ter notado que leftValue e rightValue foram escritos de forma estranha. Existem várias maneiras de declarar variáveis ​​em Lua, e esse estilo é útil quando você deseja usar menos linhas de código para definir variáveis. Observe que a linha

    leftValue local, rightValue = 0, 0

    poderia ser tão facilmente escrito como

    local leftValue = 0 local rightValue = 0


    Em cada uma das funções de entrada, verificamos o inputState, que apenas diz que tipo de evento de entrada acionou a função. Neste caso, só nos importamos quando o jogador pressiona uma tecla (Enum.UserInputState.Begin) e quando eles soltam a chave (Enum.UserInputState.End) Em onLeft e onRight, se a tecla correspondente for pressionada, definimos a variável correspondente como 1. Se a tecla foi liberada, o valor é definido como 0. Em onJump, definimos a variável de salto como verdadeira quando a entrada de salto começa, e como falsa quando a entrada termina.

    Em onUpdate, primeiro verificamos se o personagem do jogador existe e se ele Humanóide está intacto. Nesse caso, verificamos se a variável de salto foi definida como verdadeira. Se for, então definimos o Saltar propriedade do Humanóide do jogador como verdadeira.


    ⚠️Aviso Você não precisa definir a propriedade Jump como falsa a qualquer momento. O mecanismo Roblox cuidará disso para você automaticamente.


    onUpdate a seguir descobre em qual direção mover o caractere subtraindo leftValue de rightValue. Lembre-se de que essas variáveis ​​podem ser definidas individualmente. Se ambos forem pressionados, o resultado será 0, o que significa que o personagem não se moverá. Se uma das teclas for mantida pressionada, um dos valores será 1 e a diferença será 1 ou -1. Em seguida, chamamos o Mover função no Humanóide do personagem, passando a diferença que acabamos de calcular. Esta função forçará um personagem a se mover na direção que fornecemos. Como apenas definimos um valor na dimensão X, o personagem só será capaz de se mover ao longo desse eixo.

    Conclusão

    Com a combinação de câmera e scripts de controle, agora podemos configurar nosso jogo Roblox para operar como um jogo de plataforma 2D. Se você deseja adicionar ou expandir o sistema que configuramos aqui, preste atenção ao usar Scripts e LocalScripts. Lembre-se, se houver uma mecânica de jogo que afetará todos os jogadores (como uma armadilha, plataformas móveis, etc), então isso deve ser implementado em um Script. Se você estiver adicionando novos controles ou feedback específico do jogador (como um movimento de traço, salto duplo, efeitos de desvanecimento da câmera), eles devem ir em um LocalScript.

    Adicione um comentário do Tutorial: Como fazer um jogo de plataforma 2D
    Comentário enviado com sucesso! Vamos analisá-lo nas próximas horas.