Aprenda a: Programar na Roblox em Lua com o Desenvolvedor fly_san
Este é um dos tutoriais vencedores do Desafio Mestre do Conhecimento, o qual diversos desenvolvedores da comunidade da Roblox em Português competiram pelo melhor tutorial criado no Fórum dos Desenvolvedores.
O tutorial destacado neste artigo foi criado por fly_san. Tivemos uma breve entrevista com ele para entendermos como foi a sua experiência no desafio.
Fly_san está na plataforma a 7 anos e participa de diversas comunidades. Ele encontrou sua motivação para desenvolvimento enquanto explorava o Roblox Studio. Inicialmente desenvolvia para amigos e grupos que pediam a sua ajuda, e com o tempo foi aprimorando diversas habilidades, como construção, design e programação.
Também perguntamos como foi sua experiência no desafio:
“Como alguns dizem, a melhor maneira de aprender é ensinando. Fazer um tutorial é uma oportunidade de revisitar conceitos e tentar explicá-los a outras pessoas de forma mais simples e resumida. Para mim, foi uma experiência muito divertida! Apesar de eu ter começado um pouco atrasado (três dias antes do prazo), foi uma experiência muito rica.
Pessoalmente, já fazia um tempo que eu queria fazer um tutorial mais descontraído, para iniciantes; o desafio do Mestre do Conhecimento foi a oportunidade perfeita para me motivar. Além disso, o feedback do pessoal foi incrível: as respostas, votos e likes me deixaram muito feliz!”
Ansiosos para aprender a programar em Lua? Confira esse tutorial de fly_san
Em um mundo cada vez mais digital, uma das ferramentas que vem crescentemente ganhando relevância é habilidade em programação.
Lua é uma linguagem de programação simples e direta, além de possuir uma série de aplicações, é utilizada em diversos jogos mundialmente conhecidos. Além disso, Lua foi desenvolvida na PUC-RJ, no Brasil!
Então, por que não começar a aprender Lua enquanto se diverte?
1. Vamos lá?!
Abrindo o Roblox Studio
Para começar, abra o Roblox Studio. Se ainda não o tem instalado, clique aqui para ler a respeito.
Programar é o processo de criar instruções para serem seguidas por um computador.
- No Roblox Studio, essas instruções podem ser dadas através de scripts. Esses scripts dão ao jogo, uma série de instruções, que serão efetuadas durante a execução de uma partida/servidor.
Agora que estamos prontos, vamos inserir uma [ Script ]
no seu jogo. Para isso, clique no botão de mais ao lado de ServerScriptService
, pesquise por “Script” e tecle enter.
Clique duas vezes no novo objeto [ Script ]
- se fez tudo como indicado, você deve estar vendo essa tela:
Esse é o Script Editor, ferramenta que nos permite editar e visualizar nosso código.
2. Output / Console
Debugging — análise de erros
Output é uma ferramenta que nos ajuda a entender melhor o que acontece durante a execução do nosso código.
Para abrí-la, clique em “View” e depois em “Output”, como a seguir:
a) Print
Podemos enviar mensagens para o Output usando uma função chamada de print()
. Para isso, basta escrevê-la dentro do Script Editor!
print("Olá pessoal!")
-- Para escrever um texto (string), colocamos ele entre aspas!
print(12345)
-- Mas, não precisamos colocar números entre aspas.
Atenção: A parte a seguir não deve estar no seu código! Aqui, ela apenas representa o que aconteceria em seu Output se executássemos a script acima
>>> OUTPUT: Olá pessoal!
>>> OUTPUT: 12345
Quer tentar você mesmo? Onde está escrito print("Hello world!")
na sua script, apague e escreva algo mais legal. Clique em “Run” e fique de olho no seu Output!
Além disso, você percebeu que o código foi executado na ordem em que você o escreveu?
Isso sempre irá acontecer, mas é possível fazer um código rodar sem que ele pare os outros; porém esse é um tutorial para iniciantes!
b) Strings e Números
i) Strings
Se nós quisermos escrever um texto, devemos colocá-lo sempre entre aspas!
-- Duas strings diferentes:
"Isso é uma string", 'Eu também sou uma string!'
Esse texto se chama string
e há várias formas de manipulá-los:
- Uma das ferramentas mais úteis é o
concatenate ( .. )
, que pode unir duas strings em uma só.
"O fptbb gosta de " .. "Suco de Laranja!"
-- Os dois pontos (..) representam a função concatenate,
-- ao colocá-los entre duas strings, elas serão lidas como uma!
ii) Numbers
Já, se precisarmos escrever apenas um número (como 123 ou 4.5), não é necessário colocá-lo entre aspas.
-- Três números diferentes:
123, 0.5, 9.99999
Também podemos manipular esses números. Para fazer isso, usamos operadores matemáticos fornecidos pelo Lua.
50 + 5 -- uau!
Também é possível concatenar uma string e um número
"Eu gosto do número " .. 1000
Além disso, podemos fazer operações aritméticas entre uma string e um número, desde que a string seja composta por apenas um número!
print("10" + 5) -- O resultado é 15
c) Error
Além de mostrar aquilo que escrevemos com print()
, nós também podemos ver os erros que aconteceram durante a execução de nossa script!
print('Cem' + 25)
-- Não podemos efetuar essa operação...
-- Ambos os termos da operação devem ser números, mas 'Cem' é uma string
d) Comentários
Você já deve ter percebido, mas quando escrevemos --
, o que vem imediatamente depois, não é lido pela script! Esses são chamados de comments
e podem te ajudar a se organizar durante a escrita de um código.
3. Agora é pra valer.
Conhecimentos Básicos
a) Variáveis
Variáveis são um dos construtores básicos da sua script.
i) Definindo variáveis:
Variáveis são, provavelmente, a coisa mais importante em qualquer linguagem de programação, principalmente porque elas nos permitem escrever menos!
Digamos que você precise escrever "Gu4rana e bri9adeiro são grandes amigos"
várias vezes na sua Script.
Ao invés de repetir sempre essa frase enorme, podemos definí-la como uma variável:
local Frase = "Gu4rana e bri9adeiro são grandes amigos"
ii) Usando variáveis:
Muito bem, agora que nós sabemos usar print()
e definir uma variável , vamos dar um passo adiante!
Outra forma de usar print()
é colocando uma variável entre os parêntesis:
-- Primeiro, definimos a variável Frase:
local Frase = "Gu4rana e bri9adeiro são grandes amigos"
print(Frase)>>> OUTPUT: "Gu4rana e bri9adeiro são grandes amigos"
Lembre-se: variáveis são apenas uma forma de fazer referência a algo mencionado anteriormente!
Assim, se o valor dado à variável for um número, também podemos realizar operações aritméticas com a variável.
Exercício 1
Entendeu? Então vamos fazer um exercício!
Defina a variável chamada Data, de modo que ela tenha o valor de 21/05/2020 - 20:55
. Faça com que isso apareça no Output!
Resposta:
local Data = "21/05/2020 - 20:55"
print(Data)
Conseguiu?
Se você não conseguiu, releia mais uma vez e tente de novo! Tenho certeza que vai conseguir desta vez.
b) Manipulando objetos
No Roblox Studio, muitas vezes, nós iremos precisar manipular objetos e mudar suas propriedades. Vamos dar uma olhada?
i) Aba de propriedades
Não são apenas frases que podemos definir como variáveis! Também podemos definir funções, objetos, números inteiros e muito mais!
Um tipo básico de objeto que é importante saber manipular é uma “Part”. Vamos inserir uma em nosso ambiente de trabalho.
Agora, vamos examinar as propriedades desse objeto. Para isso, vamos abrir uma outra aba que se chama “Properties”:
Cada objeto possui propriedades diferentes que o definem. Além disso, podemos selecionar os objetos clicando neles ou os selecionando através da aba “Explorer”.
Por exemplo: vamos mudar o nome dessa Part
para “Bloco”. Basta selecionar o objeto, ir na aba de propriedades e mudar seu nome para Bloco!
ii) Manipulação através de uma Script!
Mudar as propriedades de um objeto é legal, mas nós também podemos fazer isso através de uma script!
Para acessar objetos, sempre devemos ter o modelo a seguir em mente
Vamos visualizar isso com uma Representação resumida que nos mostre a relação de grau parental entre esses objetos:
v Workspace (Objeto Pai)
- Camera (Filho de workspace)
- Terrain (Filho de workspace)
- Baseplate (Filho de workspace)
- Bloco (Filho de workspace)
Nesse modelo, o objeto “Bloco” é Child/Filho
do objeto “Workspace”, que é o Parent/Pai
. Vale apontar que, na verdade, o que acontece é isso:
v game (Objeto pai de Workspace)
v Workspace (Objeto pai de Bloco e Filho de Workspace)
- Bloco (Filho de Workspace e Descendente de game)
Game
é o objeto pai de Workspace
, mas ele sempre fica oculto para nós, meros mortais.
Além disso, o objeto game
já é uma variável embutida! Isso significa que nós não precisamos defini-la como uma variável.
Se você entendeu tudo, então vamos tentar mudar o nome do Bloco para Bloco_2
. Primeiro, devemos definir os objetos no Explorer como variáveis:
local workspace = game.Workspace
-- Espere! Não precisamos fazer isso!
-- Além de game, outra variável já embutida é "workspace".
-- Assim, não precisamos definir workspace outra vez.
Agora sim, vamos lá! Lembre-se, nosso objetivo é fazer com que Bloco
se torne Bloco_2
-- Primeiro, vamos definir o objeto "Bloco" com a variável "Tijolo":
local Tijolo = workspace.Bloco
Tijolo.Name = "Bloco_2" -- Aqui, mudamos o valor da propriedade Name
Podemos acessar todas as propriedades de um objeto assim!
Para testar nosso código, vamos clicar de novo em “Run”.
Mas atenção: essa mudança só ocorrerá enquanto você estiver no modo Play ou Run. Assim que você clicar em Stop, tudo voltará ao normal.
Exercício 2
Tudo certo? Vamos para mais um exercício!
Mude a transparência (Transparency) do objeto Bloco, filho de Workspace, para 0.5
Dessa vez, o nome da variável é por sua conta! Seja criativo
Resposta:
local parteLegal = workspace["Bloco"]
parteLegal.Transparency = 0.5 -- Como mencionado antes, números não precisam estar entre aspas
E aí, como foi? Acertou tudo?
Atenção:
Para definir a variável parteLegal
, eu usei o código:
local parteLegal = workspace["Bloco"]
Mas, você também poderia ter usado workspace.Bloco
. A sintaxe ["String"]
é útil quando queremos selecionar uma Child
que tem o mesmo nome de uma propriedade do objeto pai
Suponha que há uma parte dentro de Workspace que se chama “Name”.
local Part = workspace.Name
print(Part)>>> Output: "Workspace" -> Não queremos isso!
Para solucionar o problema, podemos usar a sintaxe de string:
local Part = workspace["Name"]
print(Part.Name)>>> Output: "Name" -> Resultado desejado!
Atenção: Vamos fazer uma pausa?
Parece algo chato ou desnecessário, mas é importante descansar a mente depois de aprender tantas coisas novas!
Faça algo diferente por 5–10 minutos; Revise o que vimos até agora; Levante-se da sua cadeira, estique suas pernas; Já tomou água hoje? Hidratar-se faz bem!
Já fez tudo isso? Então vamos lá!
c) Condições
Outra parte importante de qualquer linguagem de programação são “condições”. Elas agem como portas, que permitem a passagem ou não de pessoas, baseado em uma condição.
Condição de existência verdadeira (if then else
)
Nós podemos estabelecer condições com o método if x then y end
. O código y
apenas funcionará se x
não for falso
ou nulo
!
if <[Pudim é bom] == true> then print("Fly gosta de pudim") end
Esse é um pseudocódigo! Ele não funciona de verdade, pois deve servir apenas como exemplo! Vamos analisá-lo:
- A parte entre as chaves (
< >
) é o argumento da condição.
Se a igualdadePudim é bom
etrue
for verdadeira, prosseguimos para a próxima parte: a execução do código. No nosso exemplo, é a funçãoprint()
Note que em condições if
, para verificar igualdade entre dois termos, devemos usar o operador lógico para comparações (==
).
Já, quando estamos declarando variáveis, usamos apenas um operador binário de atribuição (=
), lembrou?
Exemplo:
local x = 10 -- Usamos = para atribuir o valor 10 à variável 'x'
local y = 10 -- Atribuimos o mesmo valor a 'y'-- Com o sinal == podemos verificar se aquilo
-- que está à direita do sinal é igual ao que está à esquerdaif x == y then -- Se x é igual a y, então...
print("Isso também é verdade!")
end
Portanto, atenção:
Não podemos usar o operador =
para comparação, apenas para atribuição de valor à uma variável! Da mesma forma, não é possível usar o operador ==
para definir uma variável.
Veja:
Como esperado, ao tentar verificar igualdade com apenas um sinal de igual (=
), o Output nos mostrou um erro!
Ao trocá-lo por dois sinais (==
), a script foi executada! Mas, como a condição 5 == 3
não é verdadeira, o Output não mostrou nenhum resultado!
Vale apontar que também é possível omitir a comparação de igualdade verdadeira (if x == true
).
local verdade = true
if verdade then
print("é verdade isso")
end
E também podemos declarar omitir uma condição de igualdade falsa (if x == false
)
local verdade = false
if not verdade then
print("Mentira!")
end
Como já foi mencionado, podemos fazer comparações entre dois objetos para ver se eles são iguais! Então, agora vamos tentar verificar se o objeto Pai de Bloco é o workspace
.
local Bloco = workspace.Blocoif Bloco.Parent == workspace then -- Workspace é pai de Bloco?
-- Se sim, então execute:
print(Bloco.Parent.Name)
end>>> OUTPUT: Workspace
Perceba que, se Bloco não for filho de workspace, nada acontecerá! Para mudar isso, podemos adicionar as condições elseif
ou else
.
elseif
- Funciona como umif
, mas seu código só passará por aqui se a primeira condição não for verdadeira!else
- Caso nenhuma das condições anteriores sejam verdadeiras, seu código irá executar o que você definir depois deelse
Exemplo: Vamos verificar se o nome do Bloco é “Gato” ou “Cão”, e se não for um desses, iremos printar “Não sou gato nem cão, sou um bloco!”
local Bloco = workspace.Blocoif Bloco.Name == "Gato" then -- O nome do bloco é Gato?
print("Miau")
elseif Bloco.Name == "Cão" then -- Se não for gato, então é Cão?
print("Au au, sou um cão!")
else
print("Não sou gato nem cão, sou um bloco!")
end >>> OUTPUT: Não sou gato nem cão, sou um bloco!
Operadores de inequação
Além disso, podemos usar os operadores >
(maior que), <
(menor que), <=
(maior ou igual a), >=
(menor ou igual a) para avaliar expressões númericas.
Para nosso exemplo, vamos tornar o Bloco totalmente transparente se ele tiver transparência menor que 1:
local Bloco = workspace.Bloco
if Bloco.Transparency < 1 then
Bloco.Transparency = 1
end
Operador de negação
Também é possível formular uma condição negativa, que so executará o código se seu resultado não for true
(verdadeira).
Vamos tentar mudar a Transparency
do bloco para 0.5, caso ele não seja transparente!
local Bloco = workspace.Bloco
if Bloco.Transparency ~= 1 then -- O operador ~= representa desigualdade
Bloco.Transparency = 1
end
d) Loops
Bem, o que vimos foi bem legal…
Mas, e se nós pudessemos fazer o Bloco lentamente desaparecer?
Isso é beeeeem mais legal que simplesmente fazê-lo desaparecer do nada! Para isso, nós podemos usar o seguinte código:
local Bloco = workspace.Bloco -- Definimos a variável como sempreBloco.Transparency = 0.1
wait(0.1) -- Espere 0.1 segundos antes de continuar!Bloco.Transparency = 0.3
wait(0.1)Bloco.Transparency = 0.6
wait(0.1)Bloco.Transparency = 0.9
wait(0.1)
Bloco.Transparency = 1
Mas isso não parece muito prático não é? Afinal, escrever a mesma coisa várias vezes é chato! Para resolver isso, vamos usar um loop.
i) While loop
Um loop do tipo while x do y end
é um loop que ocorrerá para sempre, desde que a condição x não seja nula/nil
ou falsa/false
local Bloco = workspace.Bloco-- Visto que true nunca será falso, o loop irá acontecer para sempre:
while true do
Bloco.Transparency = Bloco.Transparency + 0.1
wait(0.1)
end
Porém, temos um problema com esse código! Como dito, esse loop rodará para sempre, o que é desnecessário e ineficiente!
ii) For Loop
Há outra forma de fazer com que o loop apenas funcione até que ele atinja um objetivo. Um for loop tem a forma de: for <i> = <início, fim, taxa> do <x> end
São muitas variáveis novas! Para explicar melhor, um exemplo: vamos fazer nosso código contar de 1 até 5.
for i = 1, 5, 1 do
print(i)
wait(0.1)
end
i
é uma variável que varia de acordo com o indíce atual no número de repetições1
é o número de onde partimos5
é o número máximo1
é a taxa a qual iremos somar aoi
a cada repetição
Resultado:
Vamos ver o que acontece a cada loop:
-- Nosso loop é definido por i + 1
-- Dessa forma, a cada iteração (ciclo) no loop,
-- adicionamos 1 ao valor de i
i = 0 + 1 --> i = 1
i = 1 + 1 --> i = 2
i = 2 + 1 --> i = 3
i = 3 + 1 --> i = 4
i = 4 + 1 --> i = 5
Agora, podemos voltar ao nosso problema original: como fazer o nosso Bloco lentamente se tornar transparente?
- Sabemos que uma
[ Part ]
é transparente se sua propriedadeTransparency
for igual a 1, e que ela é opaca se for 0. - Portanto, nosso início deve ser 0 e o final 1.
- Vamos colocar uma taxa de acréscimo arbitrária de 0.1
- Também vamos esperar 0.1 segundos entre cada iteração.
local Bloco = workspace.Bloco
for i = 0, 1, 0.1 do -- A cada iteração, adicionar + 0.1 ao valor de i
Bloco.Transparency = i
print(i)
wait(0.1)
end
Exercício 3
Mais um exercício para vocês!
Faça com que o Bloco gradualmente fique transparente, e então mude seu Material para
Neon
e volte a ser Opaco lentamente!
Resposta:
local Bloco = workspace.Bloco
for i = 0, 1, 0.1 do
Bloco.Transparency = i
wait(0.1)
end
Bloco.Material = "Neon"
for i = 1, 0, -0.1 do
Bloco.Transparency = i
wait(0.1)
end
c) Tables
Introdução às Tables
Tables são outra parte importante do seu aprendizado de Lua. Tables são objetos que podem ser utilizados para guardar informações. É comum referir-se a elas como “dictionaries” ou “arrays”, em outras linguagens.
Definindo uma table
Uma table tem o seguinte formato:
local Leaders = {"fptbb", "Streeteenk", "davness"}
Acessando uma table
Podemos acessar “keys” ou “values” através do seguinte método: Table[índice]
, sendo índice a posição do termo que você deseja selecionar na tabela.
local Leaders = {"fptbb", "Streeteenk", "davness"}
print(Leaders[1])
print(Leaders[#Leaders])
-- #Table, te dará a quantidade de itens dentro de Table
Resultado:
>>> OUTPUT: fptbb
>>> OUTPUT: davness
Mas, e se eu quisesse colocar um Table dentro de uma Table? Também é possível! Chamamos isso, em geral, de “dicionário”.
local Staff = {
DET = {"Gu4rana", "bri9adeiro"},
LCL = {"davness", "fptbb", "Streeteenk"}
}
No exemplo acima, Staff é a table principal, na qual estão inseridas as tables DET e LCL.
Abaixo, temos uma Table chamada de Dados_Espionagem. Dentro dela, temos outras três tables: fptbb
, fly_san
e ["Gu4rana"]
.
local Dados_Espionagem = {
fptbb = {
["Bebida preferida"] = "Suco de laranja uwu";
["Nome completo"] = 'Fp "Raposo" Tbb';
["Profissão"] = {
Cozinha = "Assistente de Ajudante de Auxiliar de Cozinha"
}
};
fly_san = {
["Bebida preferida"] = {"Chá", "Café"};
["Nome completo"] = 'Senhor fly';
["Profissão"] = {
Cozinha = "Sub-Auxiliar de Chefe dos Assistentes"
}
};
["Gu4rana"] = {
["Bebida preferida"] = "????????";
["Nome completo"] = 'Gu1234rana';
["Profissão"] = {
["Roblox DET"] = "Portuguese and Brazilian Team",
Cozinha = "Gerente Superintendente Geral de Chefe de Cozinha"
}
}
}
Porém, perceba que para acessar fly_san
ou fptbb
, usamos Table.Key
:
local fptbb = Dados_Espionagem.fptbb -- fptbb não é string
local fly_san = Dados_Espionagem.fly_san -- fly_san não é string
Mas, para acessar ["Gu4rana"]
usamos Table["KeyName"]
local Gu4rana = Dados_Espionagem["Gu4rana"] -- "Gu4rana" é string
Dessa forma, podemos descobrir qual a bebida preferida do @fptbb com o código:
local bebidaPreferida = Dados_Espionagem.fptbb["Bebida preferida"]
print(bebidaPreferida)
Lendo Tables
Voltando à table “Dados_Espionagem”, percebemos que não é possível descobrir a minha bebida preferida usando o mesmo método que para o fptbb. Isso acontece pois eu gosto tanto de café quanto de chá, então eu tenho duas bebidas preferidas!
local bebidaPreferida = Dados_Espionagem.fly_san["Bebida preferida"]
print(bebidaPreferida)
Para descobrir as minhas bebidas favoritas, temos três opções:
i) Table[i]
Podemos usar o primeiro método que aprendemos para acessar valores:
local BebidaPreferida = Dados_Espionagem.fly_san["Bebida preferida"]
print(BebidaPreferida[1])
print(BebidaPreferida[2])>>> OUTPUT: Chá
>>> OUTPUT: Café
ii) for i,v in loop
Há outras formas de usar o for loop, que nos permitem ler tables.
for i,v in ipairs(Table) do
print(v)
end>>> OUTPUT: Chá
>>> OUTPUT: Café
iii) table.unpack()
O último método usando table.unpack()
é o mais prático e rápido se você apenas desejar ver os resultados no Output
Manipulando keys e valores
Você também pode inserir ou editar informações em uma table!
Editando um valor
local Table = {"a"}
Table[1] = "A" -- Estamos mudando a key 1 de "a" para "A"print(table.unpack(Table))>>> Output: A
Adicionando um valor
local Table = {"a", "b"}
Table[3] = "c" -- Estamos adicionando a key "c" na posição 3print(table.unpack(Table))>>> Output: a b c
Também podemos adicionar um valor sempre ao final de uma table! Lembrando que o operador #
pode ser usado para nos informar a quantidade de itens da table.
local Table = {"a", "b", "c", "d", "e", "f"}
Table[#Table] = "g" -- Estamos adicionando a key "g" na posição #Tableprint(table.unpack(Table))>>> Output: a b c d e f g
4. Conclusão
Aprender uma nova linguagem não é fácil! Se você conseguiu chegar até aqui, parabéns. Com esse tutorial, você aprendeu várias coisas novas.
- Como utilizar o Output e a função
print()
- Como declarar variáveis e usá-las dentro de uma função
- Como manipular objetos e suas propriedades
- Condições
if
- Loops
while
efor
- Tables
Eu acredito que essas sejam as ferramentas básicas para a construção de ainda mais aprendizagens futuras. Com esses conhecimentos, agora você conseguirá navegar pelo wiki de desenvolvimento sem grandes dificuldades!
Muito obrigado por ler esse simples tutorial. Por favor, não hesite em me contatar ou deixar uma pergunta caso tenha alguma dúvida sobre o tutorial.
Você pode ler também a versão original desse tutorial no Fórum de Desenvolvedores.
Caso queira saber mais sobre o desenvolvedor, você pode segui-lo no Twitter: @ComradeFly. Também não esqueça de nos seguir! @robloxdevrelptb.