Primeiras aulas do curso Lua parte 1: Crie um jogo de RPG em 2D

Lua parte 1: Crie um jogo de RPG em 2D

Introdução - Introdução

Neste curso, veremos como utilizar um computador TIC-80 Tiny Computer. Ele é pequeno e será utilizado na criação de um jogo. Neste parte do curso, criaremos um jogo com diversas funcionalidades.

Vamos rodar o jogo neste computador que está rodando dentro do computador. Abaixo, vemos a tela de início.

tela inicial com "Fuga das sombras" e, mais abaixo, logo da alura com o link, todos pixelados

Nós já disponibilizamos algumas imagens da personagem principal, que é uma heroína - mas você tem a liberdade de escolher qual te agrada mais. Ela vai se movimentar por um mapa também criado por nós, podendo se colidir com as paredes, elementos como a porta, ou um inimigo. Nós conseguiremos capturar itens, como uma chave dourada, mas também podemos ser capturados pelo inimigo.

personagem sendo perseguida

Por isso, um dos nosso objetivos é fugir para não sermos capturados. É possível criar mais inimigos, mais chaves, tornar o mapa mais complexo e diversas outras coisas. Faremos tudo isso com nosso código em Lua, suportado pelo TIC.

Precisaremos escrever um código bem extenso para fazer isso funcionar. Utilizaremos diversas boas práticas de programação, usaremos desenhos dos sprites, tanto do foreground, a heroína e os inimigos, quanto do background com o mapa, que será criado. E vamos gerar os efeitos sonoros do jogo.

Por fim, vale ressaltar que esse curso foi criado pelo instrutor Jeferson Silva (@jefrsilva) e eu, Guilherme Silveira, irei ajudá-lo gravando o curso.

Vamos criar o nosso jogo?

Introdução - Criando um personagem e fazendo ele se movimentar

Se queremos rodar um jogo, inicialmente precisaremos de um videogame; usaremos um computador capaz de carregar cartuchos e que recebe o nome de TIC computer.

Em seguida, baixaremos o TIC-80, com o qual é possível criar um jogo novo no navegador - mas não iremos fazer isso. Vamos fazer o download para baixá-lo para o computador (ou para o dispositivo mobile).

download tic

No meu caso, vou baixar para Mac OS X, e quando terminarmos de baixar o arquivo compactado, iremos abri-lo. Em seguida, poderemos mover o programa para o diretório que seja mais apropriado.

Aprenda o passo a passo do Download do TIC nas atividades.

Optamos por mover o tic80 para o diretório onde estão as demais aplicações.

tic na pasta application

Talvez você queira fazer algumas configurações no parte de segurança e permitir o acesso à aplicativos baixados da internet ou de desenvolvedores identificados.

O computador, como a maioria dos video games antigos, já tem um jogo instalado na memória. Se queremos rodá-lo, devemos usar o comando run no console. Logo veremos a tela de "Hello World!". No caso, o jogo que temos na memória é um computador com olhos piscantes.

tela de hello world com ícone pixelizado de um retângulo roxo sorridente

No entanto, o jogo que criaremos é outro, e o rodaremos em um diretório onde colocaremos o cartucho - possível de ser utilizado por você. Nós queremos que o computador seja aberto em um diretório específico, e para isto abriremos o terminal do Mac, ou do sistema operacional em uso.

Vamos acessar o local onde está o seu programa, e listar todo o conteúdo do diretório.

Aluras-Mac-mini:~ aluralaranja$ cd /Applications/tic80.app/Contents/MacOS/
Aluras-Mac-mini:MacOS aluralaranja$ ls
tic80

Agora que estamos no diretório certo, executaremos o seguinte:

Aluras-Mac-mini:MacOS aluralaranja$ ./tic80  /Users/aluralaranja/Documents/Guilherme/fuga-das-sombras/

Dentro deste diretório, encontraremos Tic-80. Como estamos no diretório correto, usamos ./ para executar o programa salvo neste local. Queremos guardar o cartucho (o jogo) em um diretório que fique bem acessível, no caso, em "Documentos > Guilherme > fuga-das-sombras".

Definido o diretório que queremos rodar nosso computador, teremos o seguinte retorno no terminal:

TIC-80 tiny computer 0.50.1
http://tic.computer (c) 2017

hello! type help for help

O próximo passo será conferir se estamos no diretório correto, executando folder no console.

>folder
>new lua
new cart is created

Dentro do diretório, iremos criar um novo cartucho usando a linguagem lua. Em seguida, salvaremos o cartucho como fuga.tic.

>folder
>new lua
new cart is created 
>save fuga.tic
cart fuga.tic saved!

Se executarmos folder novamente, veremos que foi criado o arquivo fuga.tic. Ao rodarmos o cartucho com o comando run, o jogo padrão será iniciado, porém, queremos rodar o nosso jogo, sendo assim precisaremos gerar nossas imagens.

Em aulas futuras do curso, usaremos as imagens disponibilizadas previamente por um designer. Se você consegue desenhar suas próprias sprites de jogo, tenha a liberdade para criá-las. Nós começaremos trabalhando com as nossas, mas não precisamos ser "mestres" nisso. Além dessa opção, podemos utilizar imagens baixadas da internet.

Para editarmos uma imagem, ou elementos do nosso cartucho, sairemos do terminal pressionando a tecla "Esc", e seremos direcionados para o editor de código. Porém, vale ressaltar que queremos alterar as imagens dentro do jogo, portanto, no menu superior, no alto da janela, selecionaremos o sprite, que é o editor de imagem localizado ao lado do editor de texto.

editor de imagem aberto em uma janela

Este é o editor das imagens do cartucho. Observe que estamos editando os desenhos do computador com olhinhos, mas esse não é o nosso objetivo. Podemos removê-los pressionando o ícone de lixeira, responsável por deletar.

ícone de lixeira

Porém, quando clicamos em apagar, ele só apagará os elementos que estão no quadro escuro menor, posicionado à esquerda. Teremos que ampliá-lo à direita, incluindo os elementos na seleção.

aumentando a seleção

O próximo passo será limpar os elementos; podemos diminuir a seleção do quadro pequeno. De volta ao quadro da esquerda, começaremos a desenhar o personagem após selecionarmos uma cor. A seguir, vamos esboçar um personagem.

bonequinho desenhado no editor

Ainda falta muito para que nosso personagem seja considerado "bonito", além disso, ele ficou pequeno. O quadro preto da seleção é composto por 8 pixels (quadrados menores) em cada lado. É muito pequeno, por isso vamos aumentar as dimensão adotando 16x16.

A seguir, iremos refazer nosso desenho.

O bonequinho ficou maior e mais fácil de ser visualizado. Inclusive, é possível perceber que ele tem um chapéu. Você pode usar a sua criatividade na criação dos personagens. O próximo passo será acessarmos o editor de código e escrever o trecho que desenhará o personagem na tela.

A função principal do jogo é TIC(), que atualmente está assim:

t=0
x=96
y=24

function TIC()
    if btn(0) then y=y-1 end
    if btn(1) then y=y+1 end
    if btn(2) then x=x-1 end
    if btn(3) then x=x+1 end

    cls(13)
    spr(1+t%60//30*2,x,y,14,3,0,0,2,2)
    print("HELLO WORLD!", 84,84)
end

Em seguida, vamos apagar o conteúdo já existente na função. Se queremos desenhar um sprite, adicionaremos spr dentro de TIC(). Cada imagem possui um número de identificação, e no caso queremos desenhar a imagem 0. Especificaremos isso no código.

Além de especificarmos a imagem, indicaremos a posição mais simples da tela usando outros parâmetros: 0, 0:

t=0
x=96
y=24

function TIC()
   spr(0, 0, 0)
end

Então, salvaremos o arquivo por meio do comando "Ctrl + S", e voltaremos para o terminal pressionando "Esc". Executaremos o comando run para rodar o jogo.

> run

Veremos que um pequeno desenho surgiu no canto esquerdo da tela.

desenho no cantinho

Isso indica que algo aconteceu, mas a exibição está sobreposta à tela do terminal. Isso porque faltou limparmos a tela, o que faremos pressionando "Esc" e retornando ao "editor de imagem".

Na função TIC() incluiremos cls() antes de spr(), trata-se de uma abreviação para clear screen ("limpar tela").

t=0
x=96
y=24

function TIC()

    cls()
    spr(0, 0, 0)

end

Agora, se voltarmos ao terminal e executarmos o comando run, veremos que a tela foi limpa e o desenho é mais perceptível no canto superior da tela.

tela limpa com desenho no canto

Porém, apenas uma parte do personagem está sendo exibida, porque um trecho 8x8 do personagem foi desenhado na tela, sendo que gostaríamos que fosse desenhado 16x16, isto é, dois blocos para direita seguidos por dois blocos para baixo.

Nossa imagem ficou incompleta pois a posição passada no código foi insuficiente. Faltou passarmos mais informações em spr(). Por exemplo, explicar qual é a cor transparente do desenho. No caso, falamos da cor preta.

cor transparente

Se contarmos na paleta, a cor preta ocupa a posição 0. Além disso, precisamos explicar se queremos deixar o desenho maior do que o original. O tamanho padrão dos elementos é 1.

O sexto parâmetro é referente aos casos em que queremos espelhar a imagem. Como este não é o nosso caso, vamos configurar com 0. Também não queremos rotacionar, por isso vamos adicionar outro 0.

t=0
x=96
y=24

function TIC()

    cls()
    spr(0, 0, 0, 0, 1, 0, 0)

end

Em seguida faremos a configuração que era nosso objetivo inicial, vamos definir a posição da imagem: 2 blocos para direita e 2 para baixo.

t=0
x=96
y=24

function TIC()

    cls()
    spr(0, 0, 0, 0, 1, 0, 0, 2, 2)

end

Após salvarmos as alterações e executarmos o comando run no console, o bonequinho será exibido por completo na tela.

Temos finalmente o personagem! A seguir, tomaremos alguns cuidados: o personagem está atualmente no canto superior esquerdo, e se quisermos posicioná-lo no meio da tela, teremos que mudar os valores dos parâmetros de spr().

A tela do computador tem 240 x 136 pixels. Para deixarmos o personagem no centro, usaremos esse valores divididos pela metade, ou seja, 120 e 68, respectivamente.

t=0
x=96
y=24

function TIC()

    cls()
    spr(0, 120, 68, 0, 1, 0, 0, 2, 2)

end

Salvaremos as alterações novamente e vamos fazer a execução no terminal.

bonequinho vai ficar a direita na tela

Porém, o personagem vai ficar quase centralizado na tela; ele começa a ser desenhado a partir do ponto central da tela, mas ficou um pouco mais à direita. Para que ele fique realmente centralizado, precisamos que ele suba um pouco para metade da tela, e depois, iremos movê-lo para a esquerda.

Teremos que adicionar esses valores no código, movendo-o 8 para esquerda e 8 para cima.

-- title: game title
-- author: game developer
-- desc: short description
-- script: lua

t=0
x=96
y=24

function TIC()

    cls()
    spr(0, 120 - 8, 68 - 8, 0, 1, 0, 0, 2, 2)

end

Agora o personagem ficará centralizado na tela.

Vamos ver o que foi feito: limpamos a tela, pedimos que o personagem fosse desenhado na posição equivalente ao centro da tela - porém tendo subtraído o equivalente à metade da imagem -, usamos a cor de fundo 0, tamanho padrão, sem espelhar ou rotacionar. Também movemos o bonequinho 2 blocos para direita e 2 para baixo.

Esta é a primeira versão do código, que ficou bem difícil de compreender. Para alguém que vê nosso código pela primeira vez, seria trabalhoso saber a que cada valor se refere. Vamos começar a melhorar nosso código, removendo os trechos que não são utilizados e alterando as informações da parte superior.

-- title: Fuga das sombras 
-- author: Jeferson Silva
-- desc: RPG de acao 2d
-- script: lua

function TIC()

    cls()
    spr(0, 120 - 8, 68 - 8, 0, 1, 0, 0, 2, 2)

end

O próximo passo será esclarecer o que está acontecendo no nosso código em relação à posição do jogador:

-- title: Fuga das sombras 
-- author: Jeferson Silva
-- desc: RPG de acao 2d
-- script: lua

jogador = {
     sprite = 0,
     x = 120,
     y = 68
}

function TIC()

    cls()
    spr(jogador.sprite, jogador.x - 8, jogador.y - 8, 0, 1, 0, 0, 2, 2)

end

Além disso, adicionamos as posições jogador.x e jogador.y. Observe que, para separar cada um dos elementos, utilizamos a ,. Vamos melhorar também a visualização da função TIC(), incluindo a descrição:

function TIC()

    cls()
    spr(jogador.sprite,
    jogador.x - 8,
    jogador.y - 8,
    0,  -- cor de fundo
    1,  -- escala
    0,  -- espelhar
    0,  -- rotacionar
    2,  -- quantos blocos para direita 
    2)  -- quantos blocos para baixo

end

Isto torna nosso código mais claro, e se o rodarmos novamente, veremos que o desenho será exibido. Já conseguimos desenhar o personagem no meio da tela, mas seria interessante movimentá-lo usando as setas do teclado. Temos que definir uma forma de perceber se as setas direcionais estão sendo pressionadas, ou seja, se os quatro botões (0, 1, 2, 3) foram apertados.

À medida em que eles são pressionados, queremos que a posição do jogador mude. Começaremos a construir isso no código adicionando um if na TIC(). Queremos definir que caso o botão 0 (seta para cima) seja pressionado, y será incrementado com + 1:

function TIC()
    if btn(0) then
        jogador.y = jogador.y + 1
    end

    cls()
    spr(jogador.sprite,
    jogador.x - 8,
    jogador.y - 8,
    0,  -- cor de fundo
    1,  -- escala
    0,  -- espelhar
    0,  -- rotacionar
    2,  -- quantos blocos para direita 
    2)  -- quantos blocos para baixo

    end

Vamos testar se o código está funcionando. Quando executarmos o código e tentarmos movimentar o personagem com a tecla "para cima", o bonequinho vai se movimentar para parte de baixo da tela.

Este comportamento inesperado acontece porque a orientação 0, 0 fica no extremo ponto à esquerda da tela. Por isso, y cresce para baixo e o x para direita. Essa é a orientação padrão para memórias de desenho nos monitores mais antigos. Por isso, quando pressionamos a tecla "para cima", nosso objetivo é diminuir y e fazer com que o personagem suba.

Em seguida, adicionaremos o botão para descer.

function TIC()
    if btn(0) then
        jogador.y = jogador.y - 1
    end
    if btn(1) then
        jogador.y = jogador.y + 1
    end

Salvaremos as alterações e testaremos se o as setas estão funcionando.

Agora será possível fazer com que o personagem se movimente para direita e esquerda.

function TIC()
    if btn(0) then
        jogador.y = jogador.y - 1
    end
    if btn(1) then
        jogador.y = jogador.y + 1
    end
    if btn(2) then
        jogador.x = jogador.x - 1
    end 
    if btn(3) then
        jogador.x = jogador.x + 1
    end

Se executarmos o código novamente, o bonequinho pode caminhar em todas as direções.

Nosso código ainda pode ser melhorado:

function TIC()

-- cima
    if btn(0) then
        jogador.y = jogador.y - 1
    end
    -- baixo
    if btn(1) then
        jogador.y = jogador.y + 1
    end
    -- esquerda
    if btn(2) then
        jogador.x = jogador.x - 1
    end 
    -- direita
    if btn(3) then
        jogador.x = jogador.x + 1
    end

Alcançamos o objetivo de atualizar a posição do personagem, e desenhar o personagem em uma tela vazia. Mais adiante, iremos melhorar o código, criar um fundo e as paredes. E fazer com que o personagem colida com as paredes.

Introdução - Trabalhando com um mapa

Nosso jogo já está rodando, e queremos mais interatividade com o mapa. Para isto, adicionaremos um piso e uma parede, dificultando a passagem do personagem. No editor de imagens de sprites, desenharemos os elementos do cenário. Começaremos clicando em uma posição diferente, selecionaremos uma área de 16x16 pixels e a preencheremos com a cor cinza - esta será nossa parede.

parede cinza

Depois, usaremos a cor marrom de dimensões 8x8 pixels. Queremos desenhar um mapa inteiro, como faremos isso? Acessaremos o editor de mapa e clicaremos na terceira opção do menu superior. Isto fará com que seja gerado um mapa confuso.

padrão formado de símbolo pequenos em pixels

Analisando as imagens repetidas no mapa, perceberemos que faz parte da imagem 0.

imagem 0

Por padrão, a imagem 0 é considerada especial e é utilizada como referência para o piso do mapa. Por isso, temos que mudar a posição do personagem, recortando-o e colando-o em área 32 do editor. Podemos fazer isso por meio dos atalhos "Ctrl + C" e "Ctrl + V", ou clicando nos ícones correspondentes.

mudando a posição do personagem

Em seguida, se acessarmos o terminal e executarmos o comando run, o personagem não será exibido na tela.

tela preta sem o personagem, ele sumiu

A solução do problema vai estar no nosso código. Nele, definimos que o sprite é igual a 0, porém precisamos atualizá-lo para 32:

jogador = {
    sprite = 32,
    x = 120,
    y = 68
}

Se salvarmos as alterações, o bonequinho será exibido e conseguiremos movimentá-lo conforme o esperado.

Revisando, o sprite com valor 0 é especial por ser o piso. O piso que criamos no editor de imagem será alterado para a posição 0. Se seguirmos para o editor de mapa, veremos que o padrão irá se repetir.

padrão de piso repetido

No editor de mapa, toda a tela ficou cheia com o piso marrom. Vamos desenhar uma parede - mas se tentarmos clicar em um quadrado e inserir uma parede, será impossível. É necessário selecionar o ícone da setinha para baixo no menu superior.

ícone da setinha

Após clicarmos no ícone, pode-se escolher o desenho que queremos aplicar. Selecionaremos o quadrado cinza e, em seguida, iremos arrastá-lo. Vamos fazer isso em toda a área que será a parede no cenário.

Adicionamos dois obstáculos no meio da tela também, mas se rodarmos o jogo da maneira em que está, o fundo da tela estará todo preto.

cenário sem parede

Queremos que o mapa seja desenhado na tela, assim como é feito com sprite. E da mesma maneira como, sempre que estamos no loop do nosso jogo, atualizamos as informações do jogador, limpamos a tela e desenhamos o jogador, caso spr() imprima um sprite, a função map() será responsável por desenhar o mapa.

function TIC()

    cls()
    spr(jogador.sprite,
    jogador.x - 8,
    jogador.y - 8,
    0,  -- cor de fundo
    1,  -- escala
    0,  -- espelhar
    0,  -- rotacionar
    2,  -- quantos blocos para direita 
    2)  -- quantos blocos para baixo

end

    map()
    end

Vamos imaginar que quando iniciamos o mapa, ele começa da posição 0, 0 - lembrando que falamos da posição do mapa, e não da tela.

Para especificar o tamanho do mapa, vamos definir a largura como sendo o tamanho da tela 240, e a altura será 138. Por último, especificaremos em que ponto da tela será feito o desenho. Novamente, é útil incluirmos instruções para tornar nosso código claro.

map(0, -- posicao x no mapa
        0, -- posicao y no mapa
        240, -- quanto desenhar x
        138, -- quanto desenhar y
        0, --  em qual ponto colocar o x
        0) -- em qual ponto colocar o y
end

Depois, conforme rodamos o jogo, os valores serão atualizados.

Porém, onde está o personagem? Ele sumiu da tela. Vamos entender o que está sendo feito no nosso código: atualizamos a posição do personagem, limpamos a tela, desenhamos o bonequinho no meio da tela e depois, o mapa.

É nesse momento que desaparecemos com nosso personagem. O mapa ficou sobreposto ao personagem, e para resolvermos isso, a função map() deverá ficar acima de spr().

function TIC()

    cls()
    map(0, -- posicao x no mapa
        0, -- posicao y no mapa
        240, -- quanto desenhar x
        138, -- quanto desenhar y
        0, --  em qual ponto colocar o x
        0) -- em qual ponto colocar o y
    end
    spr(jogador.sprite,
    jogador.x - 8,
    jogador.y - 8,
    0,  -- cor de fundo
    1,  -- escala
    0,  -- espelhar
    0,  -- rotacionar
    2,  -- quantos blocos para direita 
    2)  -- quantos blocos para baixo

end

Primeiro desenharemos o mapa e, em seguida, o personagem. A ordem do que desenhamos é importante, porque funciona como camadas. Agora visualizaremos o personagem, ainda que ele consiga passar pelas paredes...

tela com cenários e personagem

Temos outro problema, acima da parede superior - uma barra marrom com piso. Isso acontece porque quando desenhamos o cenário, existia um menu superior que desapareceu quando executamos o jogo. Ou seja, esse espaço já existia na tela, mas no momento da edição, ele será imperceptível.

Nós vamos resolver isso movendo a tela para cima com a ferramenta de mover (ícone de "mão"). Depois, vamos pintar os quadradinhos equivalentes ao piso e à parede.

movendo a tela para ajustar a parede

Em seguida, salvaremos as alterações, e com isso já temos o mapa.

Sobre o curso Lua parte 1: Crie um jogo de RPG em 2D

O curso Lua parte 1: Crie um jogo de RPG em 2D possui 245 minutos de vídeos, em um total de 51 atividades. Gostou? Conheça nossos outros cursos de Jogos em Programação, ou leia nossos artigos de Programação.

Matricule-se e comece a estudar com a gente hoje! Conheça outros tópicos abordados durante o curso:

Aprenda Jogos acessando integralmente esse e outros cursos, comece hoje!

  • 998 cursos

    Cursos de programação, UX, agilidade, data science, transformação digital, mobile, front-end, marketing e infra.

  • Certificado de participação

    Certificado de que assistiu o curso e finalizou as atividades

  • App para Android e iPhone/iPad

    Estude até mesmo offline através das nossas apps Android e iOS em smartphones e tablets

  • Projeto avaliado pelos instrutores

    Projeto práticos para entrega e avaliação dos professores da Alura com certificado de aprovação diferenciado

  • Acesso à Alura Start

    Cursos de introdução a tecnologia através de games, apps e ciência

  • Acesso à Alura Língua

    Reforço online de inglês e espanhol para aprimorar seu conhecimento

Premium

  • 998 cursos

    Cursos de programação, UX, agilidade, data science, transformação digital, mobile, front-end, marketing e infra.

  • Certificado de participação

    Certificado de que assistiu o curso e finalizou as atividades

  • App para Android e iPhone/iPad

    Estude até mesmo offline através das nossas apps Android e iOS em smartphones e tablets

  • Projeto avaliado pelos instrutores

    Projeto práticos para entrega e avaliação dos professores da Alura com certificado de aprovação diferenciado

  • Acesso à Alura Start

    Cursos de introdução a tecnologia através de games, apps e ciência

  • Acesso à Alura Língua

    Reforço online de inglês e espanhol para aprimorar seu conhecimento

12X
R$75
à vista R$900
Matricule-se

Premium Plus

  • 998 cursos

    Cursos de programação, UX, agilidade, data science, transformação digital, mobile, front-end, marketing e infra.

  • Certificado de participação

    Certificado de que assistiu o curso e finalizou as atividades

  • App para Android e iPhone/iPad

    Estude até mesmo offline através das nossas apps Android e iOS em smartphones e tablets

  • Projeto avaliado pelos instrutores

    Projeto práticos para entrega e avaliação dos professores da Alura com certificado de aprovação diferenciado

  • Acesso à Alura Start

    Cursos de introdução a tecnologia através de games, apps e ciência

  • Acesso à Alura Língua

    Reforço online de inglês e espanhol para aprimorar seu conhecimento

12X
R$100
à vista R$1.200
Matricule-se

Max

  • 998 cursos

    Cursos de programação, UX, agilidade, data science, transformação digital, mobile, front-end, marketing e infra.

  • Certificado de participação

    Certificado de que assistiu o curso e finalizou as atividades

  • App para Android e iPhone/iPad

    Estude até mesmo offline através das nossas apps Android e iOS em smartphones e tablets

  • Projeto avaliado pelos instrutores

    Projeto práticos para entrega e avaliação dos professores da Alura com certificado de aprovação diferenciado

  • Acesso à Alura Start

    Cursos de introdução a tecnologia através de games, apps e ciência

  • Acesso à Alura Língua

    Reforço online de inglês e espanhol para aprimorar seu conhecimento

12X
R$120
à vista R$1.440
Matricule-se
Procurando planos para empresas?
Acesso por 1 ano
Estude 24h/dia onde e quando quiser
Novos cursos toda semana