Escolar Documentos
Profissional Documentos
Cultura Documentos
com
Pequena cidadeé um tutorial destinado a ensinar a funcionalidade principal do GameMaker Studio 2 de maneira
natural e divertida. Tem três objetivos principais:
1. Ensine os fundamentos do GameMaker Studio 2 para fornecer uma excelente base para criar
jogos incríveis
2. Incentive a aprendizagem e a experimentação autodirigidas
3. Permitir participação síncrona e assíncrona para aprendizado presencial e remoto
Isso é ideal para começar com cursos de desenvolvimento de jogos ou aprender sobre a arte do jogo. Ele
abrange vários recursos principais do GameMaker Studio 2 de maneira holística e destina-se a conduzi-lo
por fluxos de trabalho comuns para prepará-los para criar seus próprios jogos.
Você não precisa saber programação de antemão, mas a programação é um componente central deste tutorial.
As sessões aqui contidas ensinam a própria linguagem do GameMaker Studio 2 (GML) juntamente com seus
recursos mais orientados visualmente.
EmPequena cidade, os jogadores controlam uma criança em uma pequena cidade idílica. Eles devem dar aos três personagens
da cidade - o padeiro, o professor e o dono da mercearia - o item que cada um deles mais deseja.
Como jogador, você deve encontrar os itens corretos e trazê-los para a pessoa certa. Como desenvolvedor, você
pode escolher onde ocultar cada item e escrever suas próprias dicas e diálogos. Eles também são incentivados
(consulte a sessão de bônus) a fornecer seus próprios recursos de arte e música posteriormente para transformar
Pequena cidadeem sua própria criação.
As versões em vídeo deste tutorial são rotuladas de acordo com os números das seções deste
documento;o conteúdo deste documento e os vídeos são os mesmos.
Você precisará receber os recursos de arte que acompanham este documento pelo instrutor junto com os
tutoriais em vídeo. Os ativos vêm como uma pasta chamadaSprites,e inclua quatro pastas preenchidas com
arquivos de imagem:
Você também precisará baixar os ativos de som necessários de AudioHero.com para este tutorial.
1.Você precisa clicar no link de resgate acima e preencher o cadastro (nome, e-mail e
senha)
a.Se eles já tiverem uma conta do Audio Hero, eles podem clicar em “Log In” e fazer
login)
2.Clique em “Inscrever-se” e, em seguida, você será solicitado por e-mail para confirmar sua conta
3.Então, depois de confirmar sua conta por e-mail, eles devem clicar no link de resgate
novamente e fazer login com seus dados
4.eles terão acesso total a uma lista de ativos de som para este tutorial, que podem ser baixados
gratuitamente
5.Você deve baixar todos os recursos de som fornecidos (15 no total) para o disco rígido
a. Se solicitado a escolher um formato de arquivo, você deve escolher “Download WAV”
b.Eles devem criar uma pasta chamadaSonse coloque todos os ativos de som nesta
pasta
c.Eles devem mover oSonspasta no mesmo local em seu disco rígido que oSprites
pasta (conforme descrito emBaixando os ativos de arte )
Se você precisar baixar novamente os ativos de som depois de criar uma conta, eles podem fazer isso acessando
https://yoyogames.audiohero.com/
Pequena cidadedestina-se a orientá-lo pelas funções mais utilizadas do GameMaker Studio 2 de forma
prática, simulando um projeto real e profissional. Por favor, note que este tutorial usa o tipo de projeto
GML do GameMaker Studio 2, então você aprenderá a codificar. Ao longo do tutorial, você aprenderá os
seguintes recursos:
● Características gerais:
○ Ambiente de desenvolvimento integrado (IDE) e interface de usuário (UI) do GameMaker
Studio 2
○ Criação e edição de Objetos, Sprites e Sons
○ Codificação do movimento do jogador
Pequena cidadeé um jogo 2D simples ambientado em uma pequena cidade pitoresca que você pode projetar. O jogador
pode encontrar e trazer itens para os três personagens em nossa cidade e ver as reações humorísticas desses personagens
como resultado.
● Sprite: uma imagem ou gráfico bidimensional usado em um jogo. Pode ser uma imagem estática de uma árvore ou
uma série de quadros animados para mostrar que o jogador está andando
4.1 Começando
Com o GameMaker Studio 2 aberto, você verá a tela de boas-vindas. Clique em “New Project” e clique em
“GameMaker Language” para criar nosso projeto. Você será solicitado a salvar seu projeto imediatamente,
então navegue até a pasta do seu projeto e nomeie-oTutorial de Pequena Cidade.
Clique em “Salvar” e, assim, você estará na interface principal do GameMaker Studio 2, também conhecida
comoInterface de Desenvolvimento Integrado, ouIDE. Aqui é onde a mágica acontece.
Essa grande área que você vê é chamada deÁrea de trabalho; é como uma grande mesa na qual você verá os
ativos nos quais está trabalhando. Essa grande coluna à direita é o seuNavegador de ativos; é aqui que você
organizará todos os seus Sprites, Sons, Objetos e outros recursos.
Você pode ver por padrão que seu Navegador de recursos tem vários ícones de pasta com rótulos. Essas pastas
são chamadasGrupos, e eles existem para ajudá-lo a organizar recursos comumente usados (Sprites, Sons,
Objetos, etc.). Você também pode adicionar novos grupos conforme necessário ou remover aqueles que não são
necessários (mas veremos isso mais adiante).
Os objetos são o coração do GameMaker Studio 2. Eles podem ser jogadores, inimigos, itens,
obstáculos, mas também podem ser barras de saúde, caixas de texto, telas de título e até coisas
invisíveis que acompanham nosso jogo nos bastidores. Em suma, se algo devefazeralguma coisa,
provavelmente será um objeto.
Clique com o botão direito do mouse noObjetosgrupo no Navegador de recursos e escolhaCriar > Objeto. (Se você não
tiver um grupo de Objetos, clique com o botão direito do mouse no Navegador de ativos e escolhaCriar grupo.)
Você verá que nosso novo objeto de jogador apareceu no espaço de trabalho e agora podemos editá-lo. A
interface que vemos quando abrimos um Objeto é chamada deEditor de objetos.
Para continuar, vamos colocar alguns ativos Sprite em nosso projeto. Aspriteé uma imagem bidimensional
que representa um personagem, inimigo, item e assim por diante. Eles podem ser estáticos ou animados.
Então, clique com o botão direito do mouse noSpritesgrupo no Navegador de recursos e escolhaCriar > Sprite.
Você criará um novo Sprite, que abrirá automaticamente noEditor de sprites.
Clique no canto superior esquerdo, onde diz “Nome:"e renomeie este Spritespr_player_idle_down.
A seguir, clique noImportarbotão. Na caixa de diálogo que aparece, navegue até a pasta Ativos
que você baixou para este curso. Abra oSpritespasta e depois oPersonagens e itens pasta.
Escolha a imagem chamadaspr_player_idle_down_strip04e clique em "Abrir" para selecionar esse Sprite. O que
você provavelmente verá é isto:
A imagem que importamos é chamada deFaixa de Sprite. Ele contém vários quadros de animação em um único
arquivo de imagem. E devido a alguma inteligência em nome do GameMaker Studio 2, esse arquivo de imagem
deveria ter sido convertido automaticamente em uma animação!
Então, como o GameMaker Studio 2 sabe converter a imagem que acabamos de importar em quadros
separados de animação? Bem, ele usa dois critérios:
Por exemplo, a imagem que acabamos de importar tem 1012 pixels de largura e o nome do arquivo diz _
strip04. GameMakerStudio 2 verifica se 1012 ÷ 4 = um número inteiro (o que acontece: 253).
Se uma imagem que você importou não foi convertida em quadros de animação corretamente, veja o que você pode fazer
para corrigir isso.
No Sprite Editor, clique no botãoEditar imagembotão. Você será levado a uma versão grande do seu
Sprite com várias ferramentas de desenho e seleção.
Observe que fazer isso abriu uma nova guia na parte superior do IDE. Você pode clicar noxnesta guia para fechá-la
a qualquer momento, ou você pode clicar na guia “Espaço de trabalho” para voltar para onde estávamos.
Na barra de menus na parte superior do IDE, clique emImagem > Converter em molduras.Esta nova janela nos
permitirá “cortar” nosso Sprite em quadros individuais.
- Número de quadros: 4
- Molduras por Fila: 4
- Largura do quadro: 253
- Altura do quadro: 328
CliqueConverterpara fechar esta janela. Se vir uma caixa de diálogo avisando que você está prestes a fazer
alterações, clique emOK.Você verá que nosso jogador Sprite agora foi dividido em quatro quadros.
Olhe para aspr_player_idle_downsprite novamente em seu espaço de trabalho. Se você não o vir, encontre este Sprite em
seu navegador de recursos e clique duas vezes nele para abri-lo novamente.
Agora, só precisamos fazer uma última coisa: viu como nosso player Sprite tem um pequeno alvo cinza no canto
superior esquerdo? este é o seuorigem—o ponto a partir do qual estaremos verificando os objetos e rastreando a
posição do jogador.
Por enquanto, basta clicar e arrastar o ponto de origem para algum lugar entre os pés do jogador.
O sprite do primeiro jogador, corretamente dividido em quadros, com seu ponto de origem movido
Com isso completo, você pode fechar o Sprite clicando no botãoxno canto superior direito da janela do Sprite Editor.
(Observe que o GameMaker Studio 2 salva automaticamente seus ativos conforme você trabalha neles.)
Volte para o objeto do seu jogador (obj_player);se ainda não estiver aberto em seu espaço de trabalho, basta
clicar duas vezes no navegador de ativos. Você verá que tem uma caixa branca genérica para uma imagem e um
menu suspenso que diz: "Sem Sprite". Clique neste menu e escolha o novo spr_player_idle_downSprite que
acabamos de fazer.
Voilá!Nosso jogador agora tem um Sprite anexado a ele. (Caso contrário, seria apenas um nada invisível e isso
não é divertido.)
Agora que temos um objeto de jogador que podemos ver, vamos colocá-lo em uma Sala! Felizmente, já
temos um para usar porque o GameMaker Studio 2 sempre cria um Room para nós por padrão.
No Navegador de ativos, abra a pasta chamadaquartose clique duas vezesSala 1.Vai abrir nossa
primeira Sala, que é, admito, bem chata.
ASalano GameMaker Studio 2 é como um nível ou cena em seu jogo. Mas é mais do que isso; uma Sala pode ser
uma tela de título, uma tela de carregamento, uma tela de créditos ou quase qualquer outra coisa. Mas como o
nome indica, é umlugar onde as coisas acontecem.
No momento, porém, nada de interessante está acontecendo. Então, vamos mudar algumas coisas. À esquerda
está o seu Room Editor, que tem todo tipo de coisas importantes. De cima para baixo, você verá:
● Camadas da sala:é aqui que colocaremos objetos, imagens de fundo e muito mais
● Propriedades da Camada:isso permite que você altere todos os tipos de coisas para uma camada específica
● Configurações da sala:aqui podemos alterar o tamanho da sala e editarCâmeras, o que faremos mais
tarde
Por enquanto, clique noFundocamada e olhar para o seuPropriedadesna seção no canto inferior esquerdo.
(Se as coisas parecerem espremidas ou fora do caminho, você pode ajustar o tamanho das diferentes seções
aqui.) Clique naquele vazio preto ao ladoCore escolha a cor que quiser. Uau! Algo interessante!
Agora, clique noInstânciascamada na seção Camadas. Em seguida, olhe para o seu Asset Browser (ele
ainda deve estar à direita do IDE). Encontre nossoobj_playerObjeto e arraste-o para a sala para colocá-
lo.
Embora tenhamos criado um jogadorObjeto, ao arrastá-lo para nossa Sala, criamos uminstânciadesse
Objeto na Sala. É por isso que o nome padrão da camada éInstâncias.Você pode renomear esta
camada como quiser, mas para este tutorial, vamos deixá-la como está.
(Você pode ver abaixo os ícones da lista de camadas que representam outros tipos de camadas.)
Uma última coisa antes de continuarmos; devemos renomear nossa sala para facilitar o rastreamento mais tarde. No Navegador
de ativos, clique com o botão direito do mouse emSala 1 (ou qualquer que seja o nome do seu quarto solitário) e escolha
Renomear.Digarm_gameMain.
Ok, vamos executar nosso jogo pela primeira vez e ver o que é o quê.
(Primeiro, se você ainda não o fez, certifique-se de salvar seu projeto enquanto trabalha neste curso. Vá
paraArquivo > Salvar projetona barra de menus ou use o atalho de teclado apropriado para sua
plataforma.)
Clique noCorrer botão na parte superior do IDE e veja como nosso “jogo” ganha vida! Você deve
veja nosso jogador fazendo suas coisas na Sala. Observe que a velocidade com que ela anima agora é baseada
nessaFPSopção naquele primeiro Sprite que importamos.
Incrível. Assim que sua mandíbula estiver de volta no lugar, feche a janela do jogo e volte para o GameMaker
Studio 2.
Ok, agora precisamos fazer nosso jogadorfazeralgo. Vá para o seu espaço de trabalho novamente (lembre-se, você
pode ver as guias na parte superior do IDE; uma deve se chamarEspaço de trabalho 1ou algo semelhante).
Se ainda não estiver aberto, localizeobj_playernovamente no Navegador de recursos e clique duas vezes nele para abri-
lo.
À esquerda do editor de objetos, você verá algumas opções principais e à direita você veráEventos, que
atualmente está vazio. (Se você não vêEventos,basta clicar noEventosbotão à esquerda.)
Tudo no GameMaker Studio 2 acontece em um Evento; por exemplo, quando um jogador pressiona uma tecla
ou clica no botão do mouse, isso é um evento. Existem Eventos especiais para todos os tipos de coisas, muitas
das quais vamos jogar neste curso.
Vamos adicionar nosso primeiro Evento aobj_playerclicando noAdicionar Eventobotão. Você verá uma grande lista de
eventos diferentes e até mesmo alguns em sub-listas. Por enquanto, basta escolherCriar.
OCriarO evento acontece quando um Objeto é “criado” dentro do jogo — em outras palavras, quando ele
aparece pela primeira vez. Pense em um atirador espacial onde apertar um botão atira pequenas balas; cada
um desses marcadores é um objeto e assim que eles aparecem, cada um executa seuCriar Evento.
Como colocamos uma instância deobj_playerem nosso primeiro quarto, esteCriarO evento
acontecerá assim que o objeto aparecer na sala - ou seja, assim que virmos a sala em nosso
jogo.
Por enquanto, vamos inserir nosso primeiro código emobj_player'é novoCriarEvento, abaixo do
@descriçãolinha:
// Variáveis
velocidade de caminhada = 16;
vx = 0;
vi = 0;
diretório = 3;
moverDireita = 0;
moverEsquerda = 0;
moveCima = 0;
mover para baixo = 0;
Estes são todosvariáveis. Uma variável é uma maneira de armazenar informações, chamada devalor. O GameMaker Studio 2
tem variáveis embutidas (ou seja, coisas que sempre existem), mas também podemos criar nossas próprias, como mágica.
Aqui, estamos criando diversas variáveis e atribuindo valores a elas para uso posterior.
Podemos atribuir diferentes tipos de valores às nossas variáveis, incluindo números (16, 0,2, etc.), cordas(por
exemplomeuNome = “Jimmy”;)e muito mais, mas, por enquanto, essas variáveis simples servirão.
A primeira coisa que queremos fazer é poder mover nosso objeto de jogador usando o teclado, então vamos
adicionar outro evento. Comobj_playerabra no Editor de objetos, clique emAdicionar Eventoe escolhaTecla
para baixo > direita.
Tecla pressionada Ocorre apenas quando essa tecla é pressionada pela primeira vez
moverDireita = 1;
Como você pode ver, estamos mudando ovalorda variávelmover para a direitapara1.
No Object Editor, clique em “Add Event” novamente e escolha Key Up > Right.
moverDireita = 0;
Então aqui estamos redefinindomover para a direitade volta a0quando soltamos a tecla de seta para a direita. Bastante
simples, certo? No entanto, agora tudo o que estamos fazendo é definir o valormover para a direita —é o que fazemos a
seguir que realmente permitirá que nosso jogador se mova.
Vamos adicionar mais um Evento ao nosso Objeto de jogador — oEtapaEvento. No Editor de objetos, clique em
Adicionar Eventoe escolhaPasso > Passo.Observe que existemmúltiploEtapaEventos, mas queremos aquele que acabou
de ser chamadoEtapa.
// Calcula o movimento
vx = (moveRight * walkSpeed);
// Se ocioso
se (vx == 0) {
// não fazer nada por enquanto }
// Se mover
if (vx != 0) {
x += vx;
}
Você notará nos segundos dois blocos que estamos fazendo algumas perguntas aqui sobre o valor devx. Se
você quiser verificar o valor de uma variável, você pode fazer assim:
if ([variável] == [valor]) {
// faça alguma coisa
}
Isso é chamado dese declaração. Em GML, == significa “é igual a?” e != significa “énãoigual a?"
Código Notas
// Calcula o movimento Estamos calculando o valor devxcom base em dois outros valores:mover
vx = (moveRight * walkSpeed); para a direitaevelocidade de caminhada:
caminhadapara16
Vamos testar nosso jogo novamente para você ver o que está acontecendo: clique no botãoCorrerbotão na parte superior do
IDE.
Quando a janela do jogo abrir, pressione a tecla de seta para a direita; o jogador deve se mover para a direita. Solte
a tecla de seta para a direita e o jogador deve parar de se mover.
Feche o jogo e retorne ao GameMaker Studio 2. Agora que entendemos os fundamentos do movimento
usando Eventos, podemos adicionar as outras direções.
Primeiro, certifique-seobj_playerestá aberto. No Editor de objetos, clique emAdicionar Eventoe escolhaTecla para baixo >
Esquerda.
moverEsquerda = 1;
moverEsquerda = 0;
// Calcula o movimento
v x = ((mover para a direita - mover para a esquerda)*velocidade de caminhada);
Se você está se perguntando como essa matemática funciona para fazer o objeto do jogador se mover para a esquerda, considere:
E como no evento Step usamos este código para realmente mover o objeto do jogador:
// Se mover
if (vx != 0) {
x += vx;
}
Quando terminar de se divertir, feche a janela do jogo em execução e retorne ao GameMaker Studio 2.
Agora que temos esses princípios em vigor, podemos fazer nosso objeto de jogador se mover para cima e para baixo também.
Nosso objeto de jogador fará todos os quatro eventos principais, nas variantes para baixo e para cima. Observe como adicionar uma
Descrição à linha superior de cada evento nos permite ler a lista de Eventos com mais facilidade.
Quando você tiver esses eventos no lugar, abra o evento Step novamente e edite os três blocos de código
que escrevemos da seguinte forma:
// Calcula o movimento
vx = ((moveRight - moveLeft) * walkSpeed);
vy = ((moveDown - moveUp) * walkSpeed);
// Se ocioso
if (vx == 0 && vy == 0) {
// não fazer nada por enquanto
}
// Se mover
if (vx != 0 || vy != 0) {
x += vx;
y += vy;
}
Você pode ver que adicionamos movimento vertical ao nosso player com essas adições. Também
adicionamos verificações de vy no segundo e terceiro blocos.
Com isso feito, execute o jogo novamente e tente todas as quatro teclas de seta. Você deve ser capaz de mover
o Objeto do jogador em todas as quatro direções!
É importante entender como os Eventos do GameMaker Studio 2 funcionam e entender o que são os Eventos
Key Down e Key Up. Mas e se eu dissesse que poderíamos substituir todos os oito eventos que acabamos de
criar com apenas quatro linhas de código?
Se ainda não estiver aberto em seu espaço de trabalho, abra obj_player e seu evento Step. Insira o seguinte
novo código acima do bloco de código // Calcular movimento:
Agora, no Object Editor, vamos deletar todos os oito Key Events, porque não precisamos mais deles.
Você pode clicar com o botão direito em cada evento Key Down e Key Up e escolher Delete Event. Você também pode clicar
com a tecla Shift pressionada em um grupo de Eventos de uma só vez e usar o mesmo menu do botão direito para excluí-los
todos de uma vez.
Você receberá um aviso quando fizer isso (e sim, você pode desfazer se errar).
Agora que temos nosso novo código de movimento, podemos excluir todos esses oito eventos
Depois de excluir esses eventos, execute o jogo novamente e tente usar as setas do teclado. Nosso objeto de
jogador deve estar se movendo como antes!
Então, como isso funciona? Vamos pegar a primeira linha do nosso novo código como exemplo:
moveRight = keyboard_check(vk_right);
functionNome(argumento);
A função keyboard_check() requer um único argumento — um detalhe que ela precisa para fazer seu trabalho; neste caso, a
chave que queremos que nosso jogo verifique. Aqui, estamos verificando a tecla de seta para a direita (chamada vk_right em
GML).
E, como se vê, a função keyboard_check() faz exatamente a mesma coisa que os Key Down Events que usamos no
início! Portanto, keyboard_check(vk_right) é o mesmo que criar um evento Key Down – Right.
Agora, a novidade aqui é que à esquerda do sinal =, estamos armazenando o resultado dessa função na variável moveRight,
assim:
Atualize a variável moveRight... … com o resultado que obtemos verificando se o jogador está
pressionando a tecla de seta para a direita
E como esse código está no Step Event, 60 vezes por segundo, o obj_player está perguntando: “Você pressionou a tecla
de seta para a direita?”
Agora que temos esse código de movimento atualizado, estamos prontos para fazer muito mais. Certifique-se
de salvar seu projeto e vamos em frente.
Primeiro, vamos preparar todos os nossos outros recursos. Usando o File Explorer (Windows) ou o
Finder (Mac), navegue até a pasta Ativos fornecida com este curso. Abra a pasta Sprites > Personagens e itens
e arraste esses Sprites para o grupo Sprite no Navegador de recursos do GameMaker Studio 2:
• sprPlayer_idle_up_strip04
• sprPlayer_idle_right_strip04
• sprPlayer_idle_left_strip04
• sprPlayer_walk_up_strip04
• sprPlayer_walk_right_strip04
• sprPlayer_walk_down_strip04
• sprPlayer_walk_left_strip04
Abra cada Sprite e siga os mesmos passos que seguimos em Convertendo uma Faixa de Sprite manualmente para
transformar essas faixas em Sprites com animação correta (se eles não tiverem sido convertidos automaticamente
para você).
Uma vez que cada novo Sprite Strip foi convertido corretamente em um Sprite com quadros, você pode
remover seu sufixo _stripXX.
Certifique-se de que o ponto de origem para cada um desses novos Sprites seja o mesmo que o que mais as
coisas vão ficar estranhas. Você pode ver os valores x e y de origem do primeiro Sprite (spr_player_idle_down)
clicando duas vezes no Sprite no Navegador de recursos; no canto superior direito da janela Sprite Editor estão
dois campos Origin.
Aqui, convertemos um dos Sprites do novo jogador em quadros; defina seu FPS para 10 para corresponder ao sprite
original; mudou sua origem para corresponder também; e organizou esses recursos Sprite do novo jogador dentro do recurso
Navegador
Depois de lidar com todos os novos Sprites, abra obj_player e seu Step Event novamente.
// Se movendo
if (vx != 0 || vy != 0) {
x += vx;
y += vy;
= 0; } if (vx < 0)
{ sprite_index = spr_player_walk_left;
diretório
= 2; } if (vy > 0)
{ sprite_index = spr_player_walk_down;
diretório = 3;
}
if (vy < 0) {
sprite_index = spr_player_walk_up;
diretório = 1;
}
}
Como já estamos usando vx e vy para movimento, podemos verificar aqui com várias instruções if. Não é
a maneira mais eficiente de fazer isso, mas funciona totalmente. Também definimos dir com um valor
diferente em cada caso, para que possamos usá-lo no próximo bit.
(Se você verificar o Create Event de obj_player, verá que inicializamos a variável dir em Escrevendo nosso
primeiro código GameMaker Language (GML).)
Execute seu jogo e experimente! Você deve ver seu jogador se movendo em todas as quatro direções, com os
Sprites corretos para cada direção. (Lembre-se, se o Sprite parecer “pular” conforme você muda de direção,
talvez seja necessário verificar o ponto de origem de cada Sprite.)
Nosso Objeto de jogador agora parece estar caminhando em todas as quatro direções.
Você deve ter notado um problema, no entanto; uma vez que paramos de nos mover, nosso jogador Object
continua andando, o que não é o que queremos. Vamos fechar a janela do jogo, retornar ao GameMaker Studio
2 e corrigir isso.
De volta ao Step Event do obj_player, vamos substituir o bloco “If idle” pelo novo código:
// Se ocioso
if (vx == 0 && vy == 0) {
// Muda Sprite ocioso com base na última direção
alternar diretório {
caso 0: sprite_index = spr_player_idle_right; quebrar;
caso 1: sprite_index = spr_player_idle_up; quebrar;
caso 2: sprite_index = spr_player_idle_left; quebrar;
caso 3: sprite_index = spr_player_idle_down; quebrar;
}
}
Este novo código é chamado de função switch. É uma maneira prática de combinar várias instruções if em algo
mais fácil de ler. (Você pode ler mais sobre como isso funciona no manual do GameMaker Studio 2.)
Aqui, estamos verificando a variável dir (que definimos sempre que nos movemos) e aplicando o Sprite ocioso
correto para a última direção em que o obj_player estava se movendo.
Execute o jogo novamente e veja a diferença; agora nosso jogador se move e para corretamente!
Ok, agora é hora de construir a pequena cidade do nosso jogo. Vamos abordar muitas funcionalidades
relacionadas às Salas, então vamos começar.
Usando o File Explorer (Windows) ou o Finder (Mac), navegue até a pasta Ativos fornecida com este curso. Vá
para Sprites > Backgrounds e arraste os arquivos para o Asset Browser. Como mencionado anteriormente,
você pode organizar esses recursos se quiser (por exemplo, colocando-os em um grupo de Plano de fundo da
cidade dentro do grupo Sprites).
Nossos ativos recém-importados da cidade. Organizamos esses novos recursos em um grupo chamado
"Cidade de fundo".
Você verá um monte de Sprites para coisas como árvores e arbustos e uma grande imagem
chamada spr_townTiles. Abra esta imagem no Navegador de ativos.
A maioria dos jogos constrói níveis e áreas com ativos reutilizáveis que os designers podem colocar e cutucar
para criar uma cena. No GameMaker Studio 2, podemos usar Tiles para fazer isso. Eles são exatamente como o
nome sugere; gráficos lado a lado que podemos usar repetidamente. Este arquivo (spr_townTiles) nos permitirá
projetar uma cidade criando um Tile Set.
Os Tile Sets precisam de duas peças: um recurso Tile Set e um Sprite anexado a esse recurso. Já temos o Sprite
(spr_townTiles) então só precisamos criar o ativo.
No Navegador de recursos, você verá um grupo pré-existente chamado Tile Sets. Você pode clicar com o botão
direito do mouse e escolher Criar > Conjunto de blocos. (Se você não vir este Grupo, você mesmo pode criar um.)
Clique no menu Selecionar Sprite para escolher o Sprite que você acabou de importar (spr_townTiles). Você verá
que seu Tile Set agora tem uma grade e provavelmente não faz muito sentido.
Essa grade é a grade de ladrilhos e, como você pode ver, é muito pequena. Portanto, no lado direito do editor
Tile Set, altere Tile Width e Tile Height para 400. Agora a grade deve parecer correta e você verá um espaço
em branco no canto superior esquerdo.
(Para mais detalhes sobre o editor Tile Set, você pode conferir o manual do GameMaker Studio 2.)
Nosso conjunto de ladrilhos com sprite anexado e conjunto de largura e altura do ladrilho.
Abra nossa sala única (rm_gameMain) e verifique se você pode ver o Editor de sala (a guia que nos mostra camadas
como Instâncias e Plano de fundo. Na parte inferior desta guia estão os botões de camada que mencionamos; clique
em Criar nova camada de bloco ( ) botão.
Isso criará uma nova camada chamada Tiles_1. Clique com o botão direito na nova camada e escolha Renomear;
renomeie-o para TilesMain.
Selecione TilesMain na seção Layers para que possamos editá-lo. Abaixo, em Propriedades da camada, você verá
um menu que diz "Nenhum conjunto de ladrilhos". Clique aqui e escolha o Tile Set de TilesTown que acabamos de
criar.
Você verá uma nova guia aberta chamada Room Editor e mostrará nosso novo Tile Set. Se parecer enorme ou você
não conseguir vê-lo corretamente, poderá usar as pequenas ferramentas de lupa para aumentar e diminuir o zoom.
Você deve ter notado que nossa pequena Sala é muito pequena para fazer muito, então vamos mudar isso. Na
guia Propriedades (por padrão, no canto inferior esquerdo do IDE), você verá algumas subseções que pode mostrar
e ocultar.
A primeira são as configurações da sala; se estiver oculto, clique na pequena seta para mostrar seu conteúdo e
altere estes valores:
Largura: 4000
Altura: 2400
Agora temos um espaço para brincar! Na visualização principal da Sala, você pode usar as ferramentas de lupa na
parte superior para aumentar e diminuir o zoom e pode segurar a barra de espaço enquanto clica e arrasta com o
mouse para se deslocar. Certifique-se de que você pode ver toda a sala.
Você notará uma grade na Sala que corresponde ao tamanho da Tile Width e Tile Height do nosso Tile Set (neste caso, 400).
Se você clicar no ícone Grade no canto superior direito da guia Sala,
você pode ativar e desativar a grade e verificar o tamanho da grade.
A barra de ferramentas Sala. L–R: opções de grade; Reduzir o zoom; redefinir o zoom; mais Zoom; ajuste central; mostrar visualizações;
jogar animação; selecione de qualquer camada
Por enquanto, comece a colocar Azulejos na sua Sala! Você pode “carimbá-los” um por um clicando em um ladrilho na guia Room
Editor, ou pode clicar e arrastar no conjunto de ladrilhos para selecionar e carimbar uma série de ladrilhos de uma só vez.
(Se você deseja remover um bloco, pode passar o cursor sobre ele e clicar com o botão direito do mouse.)
Projete a base para sua cidade como quiser. Preencha todos os espaços de ladrilhos da Sala e divirta-se!
Antes de continuarmos povoando nossa adorável cidade, precisamos fazer um rápido desvio para falar sobre
câmeras e viewports. (Você pode ler tudo sobre isso no manual do GameMaker Studio 2.)
Não vamos mostrar a cidade inteira de uma vez na janela do jogo, porque ela é grande. Pense em um jogo clássico de
plataforma ou RPG, onde você explora um grande mundo ou nível e o jogo “rola” conforme você joga.
Para recriar esse efeito, precisamos configurar um Viewport que seguirá o objeto do jogador conforme ele se
move pela cidade.
Com rm_gameMain ainda aberto, procure a seção Room Properties na guia Room Editor (onde alteramos o tamanho
da Room).
Você verá uma seção que pode ser expandida chamada Viewports and Cameras. Clique nele para expandir seu
conteúdo e alterar suas propriedades da seguinte forma:
Depois de tornar o Viewport 0 visível, você o verá representado no Room Editor como uma caixa branca.
Tudo bem! Agora, vamos clicar no botão Executar para testar nosso jogo novamente. Devemos ver a janela do
jogo aparecer em um tamanho de 1920x1080 e devemos ser capazes de nos mover em nossa grande cidade
recém-ladrilhada com a câmera acompanhando como fazemos.
Com nossa cidade parcialmente planejada, vamos criar um Objeto usando alguns dos outros ativos que
importamos.
Feche a janela do jogo e retorne ao GameMaker Studio 2. Volte ao seu Workspace e no Asset Browser, encontre
o grupo de Sprites de fundo da cidade que importamos. Clique duas vezes em spr_barrel01 para abri-lo no
Sprite Editor.
Na verdade, você pode colocar apenas Sprites antigos em uma camada em uma sala, mas isso significa que nosso
objeto de jogador não poderá interagir com eles. Então, vamos transformar cada um desses detalhes do ambiente
em Objetos.
Primeiro, vamos pegar esse ponto de origem em nosso barril Sprite e movê-lo para o centro inferior do
Sprite, de modo que ele se alinhe com o meio da base do barril.
Agora, no Navegador de ativos, clique com o botão direito do mouse e escolha Criar > Objeto. Nomeie este
novo Objeto obj_barrel01. Clique no menu que diz “No Sprite” e escolha spr_barrel01.
Por enquanto está tudo bem. Abra nossa grande sala (rm_gameMain) novamente e clique em Instances
camada para certificar-se de que está selecionado.
No navegador de recursos, encontre nosso novo obj_barrel01 e arraste-o para a sala. (Se você não consegue
ver seu Navegador de recursos, procure a guia Ativos; ela pode estar emparelhada com outra coisa ou a guia Editor
de ambiente ainda pode estar em foco.)
Dica: Arrastar um objeto para uma sala cria uma instância desse objeto,
para que você possa colocar quantos quiser. Se você atualizar um
Objeto, todas as suas instâncias também serão atualizadas
automaticamente.
Vá em frente e arraste mais um ou dois barris para a sala e posicione-os onde quiser.
Quando estiver satisfeito com a colocação do barril, execute o jogo novamente e caminhe. Notou algo estranho?
Você deve ter observado que:
• Os barris parecem “planos” — parece que não nos movemos na frente ou atrás deles corretamente
• Podemos apenas caminhar pelos barris
Todos os objetos em uma sala no GameMaker Studio 2 têm uma profundidade atribuída a eles. Você também notará, se clicar nas várias
camadas no Editor de ambiente, que essas camadas também têm profundidades. Você pode ler mais sobre profundidade no manual do
GameMaker Studio 2, mas aqui está uma coisa fácil de lembrar: quanto menor o número de profundidade, mais próximo o
objeto/camada/o que quer que esteja da câmera do seu jogo.
Assim, um objeto com profundidade de 10 está mais próximo (e, portanto, “na frente de”) de um objeto com profundidade de 20.
As profundidades podem variar de 16000 (totalmente para trás) a -16000 (totalmente para a frente).
Mas nosso jogo não pode determinar magicamente quais objetos devem estar na frente ou atrás de outros e quando. Precisamos dizer
isso. Então, vamos aplicar um truque rápido que chamamos de classificação por profundidade.
Abra obj_player e seu Step Event. Crie uma nova linha após os outros blocos de código (na parte inferior do evento) e adicione este
novo código:
// Classificação de profundidade
profundidade =-y;
Isso pega o valor y atual de obj_player no Room (por exemplo, 500 pixels a partir do topo) e o reverte para atribuir uma nova
profundidade a cada passo. Assim, conforme o jogador se move para baixo na Sala, sua profundidade mudará (-500, -501, -502, etc.). À
medida que sobe, muda ao contrário (-500, -499, -
498, etc). Esse truque simples funciona bem porque nosso jogo tem uma visão de cima para baixo.
No entanto, isso só funciona se aplicarmos a mesma linha de código a todos os outros objetos em nossa sala para os quais queremos
ter classificação de profundidade correta. No nosso caso agora, esses são os nossos barris.
Portanto, devemos adicionar o mesmo código de classificação de profundidade que acabamos de escrever para
obj_player ao nosso obj_barrel01, certo? Bem, não exatamente.
Veja, também queremos adicionar outros objetos com base nos ativos Sprite que importamos - como cercas, prédios de lojas, árvores
e assim por diante. Ainda nem fizemos esses Objetos, mas sabemos que teremos que lidar com eles mais cedo ou mais tarde.
Então, por que não tornar a vida mais fácil para nós e usar um dos melhores recursos do GameMaker Studio
2: criação de objetos. Com isso, podemos fazer um objeto “pai” e fazer nossos barris, árvores, cercas e outros
enfeites seus “filhos”.
Quaisquer eventos e códigos que criamos para nosso pai são herdados pelos filhos automaticamente
(a menos que digamos o contrário). Esta é uma ótima maneira de organizar Objetos que devem se comportar
da mesma maneira e lidar com eles todos de uma vez.
No Navegador de ativos, clique com o botão direito do mouse no grupo Objetos e escolha Criar > Objeto.
Vamos nomear este novo objeto obj_par_environment.
No Object Editor, adicione um Step Event. Altere a descrição para algo que seja útil para você e adicione o
mesmo código de classificação de profundidade que escrevemos acima:
// Classificação de profundidade
profundidade =-y;
Observe que no Object Editor há um botão que diz Parent. Clique aqui e depois em No Object e escolha o
obj_par_environment que acabamos de criar.
Aqui, obj_barrel01 tem obj_par_environment selecionado como pai e herdou o evento Step do objeto pai
Você notará que na lista de eventos para nosso objeto barril, um evento de etapa apareceu, mas está acinzentado.
Este é o evento de etapa herdado de obj_par_environment. Podemos substituir isso se quisermos, mas, por enquanto,
apenas deixe como está.
Agora, execute o jogo novamente e contorne os barris que colocamos. Voilá! O jogador deve aparecer corretamente
na frente ou atrás dos barris, dependendo de sua posição vertical. Agora que
parece correto!
Agora o Objeto do jogador deve aparecer corretamente atrás ou na frente de cada barril conforme ele se move
É isso para esta sessão. No próximo, vamos lidar com colisões (então não podemos simplesmente passar por
nossos barris) e muito mais. Certifique-se de salvar seu projeto!
5 Sessão 2
Bem vindo de volta! Nesta sessão, vamos fazer com que os objetos colidam entre si corretamente, criar
nossos habitantes, aplicar efeitos sonoros e música, controlar o tempo e os eventos com alarmes e muito mais!
Se você se lembra, ainda podemos atravessar nossos barris, o que não é o comportamento que queremos.
Para que um objeto reconheça outro, precisamos lidar com colisões.
Há muitas maneiras de fazer verificações de colisão no GMS2; vamos explorar alguns deles ao longo
deste tutorial, mas você pode ler sobre as outras maneiras procurando “Colisões” no manual oficial. Para
começar, porém, usaremos uma verificação simples: ponto_de_colisão.
Abra obj_player e abra seu Step Event. Vamos editar a primeira parte do // Se mover o código
bloco, que atualmente se parece com isso:
x += vx;
y += vy;
Substitua essas duas linhas por este novo par de instruções if:
if !collision_point(x+vx,y,obj_par_environment,true,true) {
x += vx;
}
if !collision_point(x,y+vy,obj_par_environment,true,true) {
y += vy;
}
Collision_point verifica um ponto x e y específico para o objeto em questão. Nesse caso, estamos olhando
adiante (usando as mesmas variáveis vx e vy que configuramos na Sessão 1) em cada eixo para
obj_par_environment. Como obj_barrel01 é um objeto filho de obj_par_environment, ele também será verificado.
Quando os Objetos verificam a colisão entre si, eles estão usando o que chamamos de máscaras de colisão.
Estes são “pontos quentes” invisíveis em cada Sprite no jogo.
Vejamos um exemplo simples. Abra spr_barrel01 no Navegador de ativos. À esquerda do Sprite Editor, você verá
uma seção chamada Collision Mask. Clique na seta ao lado para abrir esta seção.
Você notará que o Sprite agora tem uma caixa cinza escura ao seu redor. Esta é (como o nome sugere) a
máscara de colisão para o quadro atual do Sprite. Quando o objeto do nosso jogador está verificando
obj_par_envrionment, isso é o que determina se foi encontrado algo ou não. Se a colisão
máscara do quadro atual do Sprite atual para um objeto ambiental é aquele ponto preciso que o obj_player
está verificando, então a colisão é verdadeira.
Cada Sprite pode ter sua própria máscara de colisão e cada quadro de um Sprite também pode ter o seu!
Mas vamos manter isso simples. No momento, a máscara de colisão do Sprite abrange toda a imagem, mas
não é isso que queremos.
Em vez disso, queremos apenas que a máscara de colisão de nosso cano esteja em sua base. Como o jogador
pode andar na frente e atrás do cano, não faz sentido visualmente para o jogador colidir com ele se seus pés,
digamos, estiverem tocando o topo do cano.
Então, no Editor, clique ao lado de “Modo” e escolha Manual. Ao lado de "Tipo", escolha Elipse (Lento).
Você notará que a Collision Mask cinza escuro mudou de um retângulo para uma elipse. Se você clicar nesta
forma, poderá ajustá-la. (Você também pode inserir números para os quatro vértices da Collision Mask na
parte inferior esquerda do Sprite Editor.)
A Collision Mask agora está corretamente ao redor do fundo do barril. Tudo bem se a máscara se estender
além do cano assim.
Execute o jogo novamente para testar a alteração. O jogador deve parar corretamente ao se mover
contra um barril, de qualquer direção.
Já criamos nosso objeto barril, mas agora vamos criar objetos para utilizar o restante desses Sprite de
ambiente que importamos na Sessão 1.
Crie um novo objeto e nomeie-o como obj_tree01. No Object Editor, clique em “Parent” e escolha
obj_par_environment como o objeto pai.
Em seguida, clique ao lado da visualização “Sprite” no Object Editor, onde diz “none” e escolha
spr_tree01 para anexar este Sprite ao nosso novo objeto.
A configuração correta para cada um dos nossos novos objetos de ambiente: com obj_par_environment
selecionado como pai e com o Sprite correto anexado.
Você também vai querer abrir o Sprite spr_tree01 e ajustar sua origem e máscara de colisão, como
fizemos com spr_barrel01.
No Sprite Editor, faça a origem na base do tronco da árvore. Abra a seção “Collision Mask” à
esquerda do editor e altere o modo de máscara para Manual; para Tipo, escolha Elipse (lento).
Assim como você fez com spr_barrel01, ajuste a máscara de colisão elíptica para spr_tree01 para caber
na parte inferior do sprite.
Nome do objeto Sprite para anexar Tipo de máscara de colisão a ser usado
Consulte estas capturas de tela para obter detalhes sobre as recomendações de máscara de colisão e origem:
Ao criar os cinco objetos de cidade de que precisamos, você notará que spr_fountain01 é uma Sprite Strip, como as
usadas para nosso objeto de jogador.
(Se esta Faixa de Sprite não tiver sido importada corretamente com vários quadros de animação, siga as etapas em
Convertendo uma Faixa de Sprite manualmente para convertê-la.)
Quando terminar, certifique-se de organizar seus novos Objetos em um grupo no Navegador de recursos para
manter as coisas organizadas. (Clique com o botão direito do mouse no Navegador de recursos e escolha Criar grupo
e, em seguida, renomeie-o para algo como Detalhes da cidade.)
Temos uma variedade de objetos agora, então é hora de usá-los para projetar ainda mais nossa cidade e dar-lhe
alguma personalidade.
Arraste quantos desses novos objetos quiser para projetar sua cidade. (No entanto, recomendamos que
você coloque apenas três instâncias de obj_store01 e uma instância de obj_fountain.)
Se precisar, fique à vontade para reorganizar ou deletar os barris originais que você colocou na Sala (para
deletar uma Instância de uma Sala, clique nela e aperte Delete no seu teclado). Você também pode mover o
obj_player.
Dica: conforme você move as instâncias pela sua sala, você notará
que elas estão se encaixando na grade na sala (a menos que você
tenha desativado isso). Se você quiser mover uma Instância sem que
ela se encaixe, segure Alt (Windows) ou Option (Mac) enquanto a arrasta.
Usando “Flip X” em uma instância de obj_rock01. Observe como “Escala X” agora é -1.
Se você quiser alguma variedade, pode ajustar uma instância individual de um objeto dentro de uma sala.
Clique duas vezes em qualquer Instância (por exemplo, obj_rock01) e você verá as Propriedades dessa
Instância.
Há muitas opções aqui nas quais não entraremos agora, mas observe a chamada "Flip X". Se você marcar isso,
essa Instância específica será invertida horizontalmente.
Você também notará que, se marcar Flip X, a opção abaixo dela, Scale X, muda de 1 para -1.
Se a configuração Scale X ou Scale Y de uma instância for um número negativo, significa que ela foi invertida.
Você pode inserir números aqui para alterar manualmente a escala de uma Instância, ou pode clicar e arrastar nas
laterais ou cantos de uma Instância dentro de uma Sala para dimensioná-la. Se você segurar a tecla Shift enquanto
faz isso, poderá dimensionar a instância proporcionalmente.
Um objeto de rocha bastante enorme. Você pode ver a escala exata da Instância em suas Propriedades
(clique duas vezes na Instância para abri-la)
No entanto, embora seja recomendável inverter uma Instância para variar, dimensionar Instâncias dessa maneira não
é. (Mas ei, é a sua cidade!) Se quiser redefinir a escala de uma Instância, você pode alterar suas configurações de
Escala X e Escala Y de volta para 1.
Se você deseja ajustar os ladrilhos que colocou, selecione a camada TilesMain e clique na guia Room Editor para
ver o conjunto de ladrilhos que usamos novamente. Você pode remover ou alterar os blocos conforme necessário.
Dica: conforme você move as instâncias pela sua sala, você notará que
elas estão se encaixando na grade na sala (a menos que você tenha
desativado isso). Se você quiser mover uma Instância sem que ela se
encaixe, segure Alt (Windows) ou Option (Mac) enquanto a arrasta.
Nossa cidade projetada com três instâncias de obj_store01 e uma instância de obj_fountain. Observe como algumas
instâncias não parecem se sobrepor corretamente; esta certo.
Você pode perceber, ao colocar instâncias em sua sala e movê-las, que seus objetos se sobrepõem de maneiras
estranhas.
Se você quiser ajustar isso: certifique-se de que a camada Instances esteja selecionada no Room Editor; na seção
Instance Layer Properties, você verá todas as instâncias que colocou na Room. Você pode clicar e arrastá-los para
cima e para baixo para alterar sua classificação.
A ordem da instância para todos esses objetos. Você pode arrastar Instâncias para cima e para baixo na lista para classificá-las, mas
isso não é realmente necessário.
Depois de deixar sua cidade do jeito que você quer, execute o jogo novamente e caminhe por aí.
Agora é mais assim!
Caminhando pela nossa cidade recém-projetada. Observe como os objetos são classificados corretamente para profundidade.
Outra coisa que você deve ter notado enquanto caminhava pela sua cidade é que nosso Objeto de jogador ainda pode
sair do mapa, o que não queremos.
Existem muitas maneiras de lidar com isso, mas vamos fazer algo simples e visual.
Usando o File Explorer (Windows) ou o Finder (Mac), navegue até a pasta Assets fornecida com este curso e abra a
pasta Sprites > User Interface.
Arraste a imagem magenta spr_block para o grupo Sprites no navegador de recursos do GameMaker Studio 2.
No Asset Browser, crie um novo Object e nomeie-o como obj_block. No Object Editor, anexe o Sprite magenta spr_block
que acabamos de importar.
Vamos usar este objeto como uma maneira rápida e fácil de bloquear áreas que não queremos que o jogador acesse.
Para fazer isso, faça duas coisas:
Configurando obj_block. Sua opção “Visível” está desmarcada e seu pai é obj_par_environment
Abra rm_gameMain novamente e olhe para o painel Room Editor, na seção Layers. Vamos colocar
instâncias de obj_block como limites invisíveis, mas queremos fazer isso em outra camada. Por que?
Bem, isso apenas nos ajuda a nos manter organizados se precisarmos ajustar nosso quarto mais tarde.
No painel “Camadas”, clique em Criar nova camada de instância (cria ) e renomeie a camada
blocos. Você pode clicar e arrastar uma camada para alterar sua ordem (e, portanto, sua profundidade);
verifique se a camada Blocos está acima da camada Instâncias.
Em seguida, verifique se a camada Blocos está selecionada. Em seguida, arraste quatro instâncias de obj_block do
Navegador de recursos para a Sala.
No Room Editor, dimensione as quatro instâncias obj_block e reposicione-as dentro da Room para criar quatro
“paredes” bloqueando as laterais (veja a captura de tela abaixo).
Execute o jogo novamente e teste. O jogador agora deve ficar dentro dos limites da Sala. Uma vez que
tornamos obj_block um objeto filho de obj_par_environment, ele respeita o código de colisão que escrevemos
para nosso objeto player.
Feche a janela do jogo e retorne ao Game Maker Studio 2 quando estiver pronto. Se você precisar ajustar
alguma instância ou bloco em rm_gameMain, sinta-se à vontade para fazê-lo agora.
Com nossa cidade projetada, agora podemos voltar nossa atenção para os outros personagens que irão
povoá-la.
Esses personagens são conhecidos como NPCs — personagens não jogáveis — e nosso jogo terá três
deles: o padeiro, o professor e o dono da mercearia. Vamos começar com o padeiro.
No Navegador de recursos, crie um novo grupo e nomeie-o como NPCs. Arraste este novo grupo para o
grupo Sprites.
Em seguida, usando o File Explorer (Windows) ou o Finder (Mac), navegue até a pasta Assets fornecida com
este curso e abra a pasta Sprites > Characters and Items. Arraste o seguinte Sprite para o novo grupo de
NPCs que você criou no navegador de ativos:
• spr_baker_idle_down_strip04
Este é outro Sprite Strip, e deve ter sido importado para que tenha quatro quadros de animação.
Caso contrário, siga as etapas em Convertendo uma Faixa de Sprite manualmente para convertê-la. (Você
pode usar as dimensões na captura de tela abaixo para a largura e a altura do quadro.
Agora, vamos fazer uma novidade: editar um Sprite dentro do próprio GameMaker Studio 2. Se você clicar no botão Play no Sprite Editor,
verá que nosso Baker está apenas saltando para cima e para baixo infinitamente com uma longa piscada no meio, o que não é
muito interessante.
Então, vamos usar o Sprite Editor para adicionar quadros, movê-los e criar um tipo diferente de animação ociosa.
Coloque o cursor na linha entre os quadros, ele se transforma em uma seta dupla; você pode clicar e arrastar para tornar os quadros mais
longos ou mais curtos. Isso não altera o conteúdo dos quadros, apenas sua duração.
Você também pode clicar com o botão direito do mouse em qualquer quadro (ou clicar em vários quadros com a tecla Shift pressionada e clicar com o botão
direito do mouse) para copiá-los; então você pode clicar com o botão direito do mouse novamente e escolher Colar para colar os quadros na linha do tempo.
Com essas técnicas, altere o Sprite ocioso do Baker para ficar um pouco mais interessante. Certifique-se de que o último quadro seja um
pouco mais longo para criar uma pausa.
Assim como fizemos com os Player Sprites na última sessão, certifique-se de:
configuração é 8)
Quando terminar, você pode alterar o nome do Sprite para apenas spr_baker_idle_down para manter as
coisas simples (isso não afetará a animação que você acabou de editar).
Nosso Sprite ocioso Baker revisado. Observe a configuração “FPS” e o posicionamento da Origem.
Feito isso, você pode fechar todos os seus Sprites e quaisquer outros ativos (lembre-se, quando estiver em um
espaço de trabalho, você pode clicar com o botão direito do mouse no plano de fundo e escolher Windows
> Fechar tudo para limpá-lo). Precisamos criar nosso Baker Object para continuar, mas espere um momento —
precisamos criar três personagens, certo?
Embora esses três personagens sejam diferentes, eles são o mesmo tipo de Objeto: NPCs. E como sabemos
que todos os três serão o mesmo tipo de Objeto, podemos pensar adiante aqui e fazer a mesma coisa que
fizemos na Sessão 1: criar um Objeto pai primeiro.
Então, vamos criar o objeto pai para todos os NPCs e, a partir dele, criar nossos três personagens. Isso
significará, assim como aconteceu com os objetos ambientais em nossa cidade, que podemos fazer mais
com menos e nos manter organizados.
No Asset Browser do GameMaker Studio 2, clique com o botão direito do mouse no grupo Objects e crie um novo
Object. Nomeie-o como obj_par_npc. Por agora. Não precisamos aplicar um Sprite ou criar nenhum Evento; nós só
precisamos que ele exista.
Agora crie outro objeto e nomeie-o como obj_npc_baker. No Object Editor, clique em “No Sprite” e escolha nosso
spr_baker_idle_down para aplicá-lo. Por fim, clique em Parent e escolha nosso novo obj_par_npc como objeto pai.
Com isso, nosso Baker NPC agora é um Object filho se obj_par_npc, o que significa que podemos fazer alterações
no pai e o Baker herdará essas alterações.
Abra rm_gameMain e coloque uma instância do Baker na Sala, em frente a uma das lojas. Execute o jogo e observe-
o fazer suas coisas.
Colocando o Objeto Baker ao lado de uma das lojas da nossa Sala. Observe como organizamos os
objetos NPC no Asset Browser.
Então, a seguir, vamos usar o relacionamento pai-filho entre objetos para tornar nossos NPCs mais únicos e vivos e
para corrigir esse problema de profundidade.
Abra nosso objeto obj_par_npc novamente e clique no botão denominado Variable Definitions.
As Definições de Variáveis nos permitem configurar variáveis predefinidas de vários tipos e nos permitem alterar o
valor dessas variáveis em Objetos filhos, ou mesmo em Instâncias desses Objetos filhos colocados em uma Sala.
Com esse recurso, podemos configurar as coisas necessárias (como velocidade de animação ou sequências
de texto) para facilitar o acesso. É um recurso poderoso que nos permite acompanhar as coisas visualmente.
Vamos adicionar algumas novas variáveis aqui clicando no botão Adicionar. Insira o nome da variável como
loopRange01 e altere o Padrão para 30.
Você notará que há um menu suspenso denominado Tipo; aqui você altera o tipo de valor que deseja inserir para
cada variável (como números reais, inteiros, strings e assim por diante). Se você rolar o “?” ícone de dica de
ferramenta ao lado de cada tipo, você pode aprender mais. Por enquanto, porém, mantenha o Tipo definido como
Real (já que estamos inserindo números).
Adicione uma segunda variável chamada loopRange02 e defina seu padrão como 240.
Vamos usar uma combinação de Criar Evento, nossas Definições de Variáveis e um novo tipo de Evento chamado
Alarmes para tornar as animações ociosas de nossos NPCs um pouco mais interessantes.
Então, em obj_par_npc, vamos adicionar um Step Event. No Editor de objeto, clique em Adicionar evento e
escolha Etapa > Etapa.
// Classificação de profundidade
profundidade =-y;
Você já sabe o que o bloco de código // Depth sorting faz; é o mesmo que escrevemos para nossos objetos
de ambiente. Isso garantirá que nossos NPCs apareçam corretamente atrás e na frente de outros objetos na cidade.
Mas acima disso, no bloco de código // Random loop timing, está a parte divertida. Vamos decompô-lo:
alarme[0] =
irandom_range(loopRange01,loopRange02); E então, vamos definir um alarme com um número
} inteiro aleatório (mais sobre isso abaixo)
}
Observe como no código acima, estamos usando loopRange01 e loopRange02 — essas são as definições de variáveis que
configuramos em nosso objeto pai. Neste código, estamos definindo um Alarme para um valor aleatório entre esses dois
números (que, por padrão, definimos como 30 e 240, respectivamente).
Então, o que um Alarme faz afinal? Bem, como o nome sugere, é um evento que você pode definir (e redefinir) a qualquer
momento; toda vez que um Alarme “toca”, ele executa qualquer código que você tenha escrito ali.
O número para o qual você define um alarme é uma contagem regressiva em etapas - portanto, definir um alarme para 60
significa que, após 60 etapas, ele "desligará".
Seu jogo possui diversas opções associadas a ele para diversas plataformas, além de um conjunto geral.
Você pode encontrar isso acessando o Navegador de ativos e expandindo o Acesso rápido.
Aqui, você verá as opções disponíveis para você (dependendo de quais módulos de plataforma aos quais você tem acesso).
Clique em Principal para abrir as Opções do Jogo – Janela principal:
A janela principal de opções do jogo, com uma configuração de quadros por segundo de 60.
Nessas opções está o Frames do jogo por segundo, que por padrão é definido como 60. Essa é a taxa
de quadros que seu jogo tenta manter durante a reprodução — neste caso, 60 quadros por segundo, ou
FPS . Então, um passo em nosso jogo é um desses quadros por segundo.
Este não é um valor em tempo real per se; se o seu jogo ficar atolado com muitos objetos ou código
mal otimizado, ele pode ficar lento. Lembre-se disso ao configurar os alarmes.
Agora, vamos fazer um alarme simples que randomiza a animação ociosa de nossos NPCs para dar a
eles um pouco mais de personalidade.
Em obj_par_npc, adicione um Evento e escolha Alarmes > Alarme 0. (O GameMaker Studio 2 oferece
doze Alarmes possíveis por Objeto — 0 a 11 — então vamos escolher apenas o primeiro.)
// Reseta a animação
índice_imagem = 0;
velocidade_imagem = 1;
Isso redefinirá a animação de volta para o primeiro quadro (quadro 0) e o multiplicador de imagem_velocidade de volta
para 1, para que a animação seja reproduzida novamente.
Execute o jogo novamente e preste atenção: agora a animação inativa do Baker será reiniciada em intervalos diferentes,
dando a ele um pouco mais de vida. E conforme o objeto do jogador se move ao redor dele, você verá que ele aparece
corretamente na frente e atrás do nosso padeiro saltitante.
Dica: você pode adicionar mais randomização ao objeto pai do NPC. Por
exemplo, o que acontece se no Alarme 0 você alterar image_speed
para um número aleatório?
Definimos definições de variáveis em obj_par_npc para duas variáveis, mas como as usamos e o que elas fazem?
Clique no ícone de lápis ao lado de loopRange01 para alterar seu valor; tente alterá-lo para 60. Faça o mesmo
para loopRange02 e altere o valor padrão para 320.
Editando as definições de variáveis herdadas em obj_npc_baker. Observe como uma Definição que editamos aqui
aparece diferente de uma que ainda não editamos.
Execute o jogo novamente e preste atenção no Baker; você notará que a pausa no final de sua animação
ociosa ainda é aleatória, mas a pausa é mais longa.
Feche a janela do jogo e retorne ao GameMaker Studio 2. Sinta-se à vontade para retornar
ao obj_npc_baker e alterar ainda mais esses valores ou clique no botão menos ao lado de uma Definição para
restaurá-la ao padrão do Objeto pai.
Usando o File Explorer (Windows) ou o Finder (Mac), navegue até a pasta Assets fornecida com este curso e
abra Sprites > Characters and Items. Arraste os seguintes recursos para o grupo Sprites > NPCs no
Navegador de recursos do GameMaker Studio 2.
• spr_teacher_idle_down_strip02
• spr_grocer_idle_down_strip02
• Defina sua origem como antes (para baixo, entre os pés do personagem). Lembre-se, você sempre pode
ajustá-lo mais tarde, se não parecer certo
• Altere o FPS para 10
• Remova o sufixo _stripXX de cada nome de ativo
• Verifique se a Sprite Strip foi convertida corretamente em quadros de animação. Caso contrário, siga as
etapas em Convertendo uma Sprite Strip em quadros de animação para fazer isso
Clique com o botão direito do mouse no Navegador de recursos e crie um novo Objeto. Nomeie-o como
obj_npc_teacher e anexe o sprite spr_teacher_idle_down a ele.
No Editor de objeto, clique em Pai e escolha obj_par_npc para tornar o Professor um objeto filho.
1. Edite seu Sprite ocioso da mesma forma que fizemos com o Baker
2. Altere os valores de suas Definições de Variáveis
Primeiro, abra spr_teacher_idle_down novamente e edite a animação como fizemos com o Baker.
No momento, o Sprite é apenas dois quadros de animação. Brinque aqui como quiser adicionar uma cadência diferente à
animação do professor e certifique-se de esticar o quadro final para que haja uma pausa.
Crie outro objeto e nomeie-o como obj_npc_grocer. Anexe o sprite spr_grocer_idle_down a ele. Assim como acima,
torne o objeto Grocer um filho de obj_par_npc.
No Editor de objetos, clique em Definições de variáveis e altere os padrões aqui para valores diferentes (eles não
precisam ser iguais aos valores que você escolheu para o Objeto do professor).
Em seguida, abra spr_grocer_idle_down novamente e repita as etapas que demos acima para o Sprite do professor
para aprimorar a animação ociosa do Grocer; novamente, certifique-se de que o último quadro da animação tenha
uma pausa.
Certifique-se de ter a camada Instâncias selecionada e arraste uma única Instância de cada
obj_npc_teacher e obj_npc_grocer para a Sala.
Posicione os dois NPCs na frente das duas lojas desocupadas; agora nossa cidade está povoada!
Estamos no caminho certo para ter uma cidade agradável e animada. Mas vamos precisar de mais algumas peças
para fazer tudo funcionar.
Para começar, nossos três NPCs estão parados agora, sem fazer muita coisa; vamos querer interagir com eles.
Mas para fazer isso, nosso objeto jogador primeiro precisa ser capaz de perceber que eles estão lá.
Felizmente, já temos uma ideia de como fazer isso; aprendemos como verificar um objeto de outro em Criando objetos
sólidos com colisões.
Abra obj_player e seu Create Event. Adicione estas linhas ao código já existente:
Agora, abra o Step Event do obj_player. Localize ou crie uma nova linha na parte inferior, logo acima do bloco de
código // Depth sorting. Adicione o seguinte novo bloco de código:
se NPC próximo {
// faça alguma coisa
}
se !próximo NPC {
// fazer outra coisa
}
Adicione o novo bloco de código a obj_player. (A janela Event aqui é estreita, então o código continua do lado
direito.)
No Create Event, declaramos a nova variável nearNPC e a definimos como noone, que é um valor
embutido no GameMaker Studio 2 que significa exatamente o que diz. Também criamos uma nova
variável chamada lookRange.
No Step Event (lembre-se, cada quadro único do jogo), estamos usando uma verificação de colisão para
procurar um objeto (obj_par_npc).
Esta verificação de colisão é diferente da verificação de colision_point() que usamos antes, pois não verifica
um ponto específico, mas sim uma área retangular.
A área que estamos verificando é um retângulo que usa lookRange para determinar seu tamanho.
Faça lookRange um número maior ou menor e o alcance que nosso objeto de jogador verifica para NPCs
aumenta ou diminui.
Com colision_rectangle(), estamos verificando uma área ao redor das posições x e y do objeto do jogador. A
área é definida pelo valor lookRange
(Se você quiser saber mais sobre a função colision_rectangle, consulte o manual do GameMaker Studio 2.)
Dica: Se você vir uma linha de código que diz algo como
someVariable = fancyFunction(), significa que estamos usando uma
função (fancyFunction) e armazenando seu resultado
imediatamente em uma variável (someVariable). É apenas uma maneira
prática de combinar duas etapas em uma.
Abaixo da verificação de colisão do NPC próximo, você verá duas declarações if:
se NPC próximo {
// faça alguma coisa
}
se !próximo NPC {
// fazer outra coisa
}
Como passamos o resultado de nossa função de colisão imediatamente para a variável NPC próximo, podemos
verificar rapidamente se ele encontrou algo (se NPC próximo) ou não (se !NPC próximo).
Mas como podemos confirmar que isso funciona? Bem, é aí que entram as mensagens de depuração .
Às vezes, a maneira mais fácil de testar algo é fazer com que seu jogo exiba uma mensagem de depuração, para
que você possa saber se algo funciona antes de dedicar mais tempo. Isso é o que vamos fazer aqui.
No Step Event do obj_player, atualize o bloco de código // Verificar colisão com NPCs que acabamos de escrever:
Agora, execute seu jogo e faça com que seu objeto de jogador ande por aí. Preste atenção na janela Output
na parte inferior do GameMaker Studio 2 IDE. Se o seu jogador não estiver em contato com um NPC, ele
continuará exibindo “obj_player não encontrou nada!” uma e outra vez. Assim que chegar perto do Baker, Teacher
ou Grocer, a mensagem com change.
A janela Output (parte inferior) no GameMaker Studio 2 pode exibir mensagens de depuração, que podemos usar para verificar
rapidamente as coisas.
Assim como com o código que escrevemos para verificar obj_par_environment, este código
colision_rectangle() está verificando obj_par_npc. Como obj_npc_baker, obj_npc_teacher e obj_npc_grocer são todos
filhos de obj_par_npc, a verificação ainda é válida.
Como você deve ter notado ao testar o novo código de colisão do objeto do jogador, atualmente temos que nos aproximar muito de
um NPC para que o nosso objeto do jogador o reconheça.
Isso ocorre por causa das máscaras de colisão que cada Sprite possui (exatamente como discutimos nas máscaras de colisão).
Lembre-se, sempre que qualquer verificação de colisão estiver sendo feita, a máscara de colisão de um Sprite é o fator
determinante.
Então, vamos primeiro editar a máscara de colisão para o nosso Sprite ocioso do Baker, para ter certeza de que está como queremos.
Abra spr_baker_idle_down no Sprite Editor. À esquerda do editor, clique em Collision Mask para revelar a máscara para este
Sprite.
Você verá que a máscara de colisão aqui é um problema. Primeiro, cobre a maior parte do Sprite, o
que não faz sentido. Dada a perspectiva de cima para baixo do nosso jogo, queremos apenas que o Objeto
do jogador detecte o Padeiro quando ele se aproximar. Com a máscara de colisão como está, o
Objeto do jogador pode “colidir” com o Padeiro, mesmo que esteja atrás e acima dele.
Pensando nisso, procure ao lado de “Modo” e clique em Automático (ou na seta ao lado). Em vez disso,
escolha Manual e edite a máscara de colisão para abranger apenas a área ao redor dos pés do Baker, assim:
A máscara de colisão editada para spr_baker_idle_down. Observe que a máscara de colisão é generosa e
que se estende além do próprio Sprite.
Por que não estamos editando os Sprites para obj_player também? Isso ocorre
porque a verificação de colisão_rectangle() que escrevemos em Detectando os NPCs é muito
específica (como demonstrado no diagrama nessa seção) e não está usando Sprites do obj_player para
detectar colisão.
Se você quiser fazer uma verificação de colisão simples, também pode usar um evento de colisão. Não os
usaremos para este tutorial, mas para fazê-lo:
- Abra o objeto no navegador de ativos
- No Editor de objetos, clique em Adicionar evento e escolha Colisão > Objetos > [objeto]
Um exemplo de um evento de colisão simples. Não os usaremos para este tutorial em particular.
De volta ao assunto em questão: quando você tiver editado a máscara de colisão para spr_baker_idle_down,
execute o jogo novamente e faça com que o objeto do jogador caminhe até o padeiro. Os pontos em que o Objeto
do jogador reconhece o Padeiro devem fazer muito mais sentido.
Se você acha que a colisão não está correta (ou seja, você deve chegar muito perto, ou funciona se você estiver
muito longe), você também pode editar o valor de lookRange no Create Event do obj_player.
(Não se esqueça, procure na janela Saída na parte inferior do IDE as mensagens de depuração que escrevemos.)
Agora, o alcance no qual o Objeto do jogador detecta o Padeiro faz mais sentido.
Quando estiver satisfeito com a Collision Mask for the Baker, repita essas etapas para:
• spr_teacher_idle_down
• spr_grocer_idle_down
Agora que nosso jogo está bonito, é hora de fazer com que pareça bom também. Vamos aplicar alguns efeitos
sonoros e música e experimentar o áudio 3D.
Usando o File Explorer (Windows) ou o Finder (Mac), navegue até a pasta Assets fornecida com este curso e
abra a pasta Sounds.
Dica: Se você não tiver certeza de onde estão seus recursos de som,
consulte as instruções em Baixando os recursos de som do AudioHero
Arraste esses arquivos para o Asset Browser do GameMaker Studio 2, dentro do grupo Sounds (se você
tiver um). Se você não tiver um grupo de sons, crie um e coloque esses novos ativos de som lá.
Abra o ativo chamado snd_townBGM (“BGM” significa “música de fundo”, caso você esteja se
perguntando). No Editor de Som, você verá algumas opções simples:
O Editor de som nos permite alterar o volume base de um recurso de som, a velocidade de reprodução,
lidar com a compactação e outras opções. (Para obter detalhes sobre todos os recursos do Sound Editor,
consulte o manual do GameMaker Studio 2.)
Por enquanto, porém, só precisamos mudar uma coisa. Abaixo da opção de destino “Saída”, clique no menu
suspenso (provavelmente será Mono por padrão) e escolha Estéreo. Queremos garantir que nossa bela música
de fundo seja ouvida corretamente.
Feche o Sound Editor e clique com o botão direito do mouse no grupo Objects no Asset Browser para criar um
novo Object. Nomeie-o como obj_control. Este objeto será um “objeto de controle” invisível —
pense nisso como o diretor de uma peça, certificando-se de que certas coisas corram bem nos bastidores.
Em seguida, clique em Adicionar evento. Escolha Outro > Início da sala. Este é um evento especial que ocorre
(como você deve ter adivinhado) apenas quando entramos em uma sala pela primeira vez. É diferente do
Create Event, que ocorre quando um objeto aparece pela primeira vez.
Esta é outra função de troca (que abordamos primeiro em Alterar os sprites do jogador). Neste caso,
estamos verificando qual Room acabou de começar e, como só temos um Room, há apenas um
caso.
Você pode ler mais sobre esta função básica de áudio (audio_play_sound()) no GameMaker
Manual do Studio 2, mas aqui está uma análise rápida:
audio_play_sound( snd_townBGM, 1, 1 );
Abra rm_gameMain no Room Editor e arraste nosso novo obj_control para as Instances
camada. Não importa onde você o coloca, já que é invisível, mas eu recomendo que você o coloque do lado de fora da
Sala no canto superior esquerdo, para que possa encontrá-lo facilmente mais tarde.
Com nosso novo objeto de controle no lugar, execute o jogo novamente e deleite seus ouvidos - música!
Quando terminar de curtir as músicas, feche a janela do jogo e volte ao GameMaker Studio
2.
No grupo Sons do Navegador de ativos, abra snd_townAmbience. Assim como fizemos com snd_townBGM,
queremos fazer uma alteração neste ativo.
No Sound Editor, clique no menu em “Output” e mude para Stereo (assim como fizemos com a música de
fundo).
Atualize o // Reproduzir música com base no bloco de código da sala da seguinte forma:
Isso reproduzirá a adorável música de fundo e o agradável ambiente campestre ao mesmo tempo.
Para testar isso, execute o jogo novamente. Você notará que a música agora parece um pouco alta
em comparação com o loop ambiente.
Abra snd_townBGM novamente no Navegador de ativos. No Editor de som, preste atenção aos controles de reprodução
(abaixo de onde diz “Volume”).
Você pode clicar no botão de reprodução aqui para visualizar um recurso de som. Você também pode ajustar seu
volume movendo o primeiro controle deslizante triangular em “Volume” ou alterando manualmente o valor do
número ao lado dele.
Quando terminar, execute o jogo novamente e ouça os resultados. Se a mixagem ainda não estiver correta, ajuste
o volume de snd_townBGM até ficar satisfeito.
Tudo bem, vamos adicionar mais som ao nosso jogo. Faremos com que o objeto do nosso jogador diga
algo sempre que encontrar outro personagem.
Também vamos utilizar o restante dos ativos de som que importamos no restante do curso. Para nos
poupar algum tempo mais tarde, vamos fazer uma alteração rápida em vários ativos de som.
Abra os seguintes recursos de som no navegador de recursos e altere sua configuração de saída para
Estéreo:
• snd_gameOver
• snd_greeting01
• snd_itemPickup
• snd_itemPutDown
• snd_pop01
• snd_pop02
• snd_seq_bad01_BGM
• snd_seq_bad02_BGM
• snd_seq_bad03_BGM
• snd_seq_good01_BGM
• snd_seq_good02_BGM
• snd_seq_good03_BGM
Abra obj_player e seu Step Event. Vá para o bloco de código // Verificar colisão com NPCs e atualize-o da seguinte
forma:
Estamos incluindo exatamente a mesma função de áudio que usamos para reproduzir a música de fundo, exceto
que o último valor é 0, o que significa que este não fará um loop.
No entanto, há algo que você deveria ver (ou melhor, ouvir). Execute o jogo novamente e mova o jogador para
que ele colida com um dos personagens, depois fique parado.
Oh garoto, isso não é bom! Mesmo que a função de áudio esteja configurada para não repetir, você pode ouvir que nosso
player está cumprimentando o NPC repetidas vezes. Isso ocorre porque na etapa do objeto do jogador
Evento, estamos usando aquela linha NPC próxima para verificar se há um NPC. E se isso for verdade, o jogo tocará
nosso som de saudação.
No entanto, queremos que nosso jogador diga sua saudação apenas uma vez cada vez que colidir com outro
personagem, então como podemos consertar isso? Como se vê, muito simplesmente.
Muitas vezes, quando precisamos ser específicos sobre quando ou como algo acontece, podemos usar uma variável e
alterar seu valor como uma técnica de controle simples.
cumprimentou = false;
Agora volte para o Step Event do obj_player e vamos editar o código do NPC mais uma vez:
O que fizemos foi usar essa nova variável, hasGreeted, para determinar se nosso jogador já disse “olá”. Quando o
jogador colide com um NPC, ele verifica essa variável e se for falso, tocamos o efeito sonoro de saudação. Em seguida,
definimos hasGreeted como true, para que o som não seja reproduzido novamente.
Finalmente, quando o jogador não está colidindo com um NPC, ele verifica se hasGreeted foi definido como 1 e
redefine-o como falso, para que da próxima vez que abordarmos um de nossos personagens, nosso jogador diga
“olá” novamente (apenas uma vez).
Execute o jogo e veja nosso jogador muito mais educado em ação. Isso é melhor!
Vamos fazer uma última coisa aqui. Às vezes, você realmente deseja controlar quando um som é reproduzido e
não permitir a sobreposição ou duplicação de sons. Então, no Step Event do obj_player, vamos fazer uma última
edição no código do NPC próximo:
Tudo o que adicionamos aqui é mais uma verificação: para ver se o som de saudação (não) já está tocando e,
em seguida, reproduza o som.
Execute o jogo novamente e experimente. Mesmo que você caminhe rapidamente até um personagem repetidas
vezes, o Objeto do jogador não tocará seu som de saudação até que termine de fazê-lo. Pode não parecer fazer
muita diferença, já que snd_greeting01 é tão curto, mas essa mudança ainda ajudará nossa paisagem
sonora a parecer um pouco mais natural.
Ok, agora vamos realmente ficar chiques. Temos música de fundo, temos um exemplo simples de efeito
sonoro padrão, mas e o áudio 3D?
O que vamos fazer é pegar aquela grande fonte que temos em algum lugar da nossa cidade e fazer com que ela
reproduza um efeito sonoro em loop. A diferença aqui será que será posicional, de modo que conforme o Objeto
do jogador se move pela cidade, poderemos ouvir onde está o som da fonte, em relação à posição do jogador.
Para usar o áudio 3D, precisamos de dois componentes: pelo menos um Emissor e um Ouvinte.
Um Emissor faz exatamente o que o nome sugere; ele emite (ou reproduz) um recurso de som. Um Ouvinte
pode ouvir os Sons que um Emissor toca, e é a relação entre esses dois que cria o efeito posicional.
Primeiro, vamos garantir que temos um Ouvinte configurado. Normalmente, definimos o Ouvinte em um jogo
como nosso Objeto do jogador. Então, abra obj_player e abra seu Create Event.
No Create Event, adicione alguns espaços abaixo das variáveis que escrevemos anteriormente e adicione estas
linhas de código:
Você pode ler mais detalhes técnicos sobre essa segunda linha no manual do GameMaker Studio 2, mas o que
você precisa saber aqui é simples: a primeira linha define a posição do Audio Listener do jogo para os valores x e
y do jogador e a segunda linha define corretamente dentro do espaço 3D.
Em seguida, abra o Step Event do obj_player e encontre o bloco de código // If Moving. Atualize esse bloco de
código assim, para adicionar estas novas linhas:
// Se mover
if (vx != 0 || vy != 0) {
if !collision_point(x+vx,y,obj_par_environment,true,true) {
x += vx;
}
if !collision_point(x,y+vy,obj_par_environment,true,true) {
y += vy;
(vx < 0)
{ sprite_index = spr_player_walk_left; diretório
= 2; } if
(vy > 0)
{ sprite_index = spr_player_walk_down;
diretório
= 3; } if (vy < 0)
{ sprite_index = spr_player_walk_up;
diretório
= 1; }
Este é o mesmo código que está no Create Event. Nós o incluímos aqui para que, à medida que o jogador
se mova, ele atualize a posição do Ouvinte de áudio para a sua. (Não há necessidade de continuar fazendo isso
se o jogador estiver parado, e é por isso que estamos colocando apenas dentro do bloco de código de movimento.)
Execute o jogo e observe que até agora, tudo o que fizemos com o áudio é o mesmo. É somente quando
adicionamos emissores que as coisas ficam interessantes.
Quando estiver pronto, feche a janela do jogo e retorne ao Game Maker Studio 2.
Queremos que nosso Objeto fonte emita um efeito sonoro em loop que o Ouvinte do jogo captará no espaço 3D,
então precisamos criar um Emissor e reproduzir seu áudio por meio dele.
Como a fonte é filha de um Objeto pai (obj_par_environment), no entanto, faz mais sentido adicionar essa
funcionalidade ao Objeto pai e permitir que qualquer um de nossos Objetos ambientais o use.
Dê a esta nova definição de variável use o nome useSound. Faça seu Type Asset e digite noone
por seu padrão.
Escolher o tipo de variável Asset nos permite restringir as escolhas aqui para tipos específicos de assets
(Sprites, Sounds, etc.). Clique no ícone de engrenagem ( ) em Opções e escolha Sons na janela Opções que
se abre.
Para concluir esta etapa, clique no menu suspenso em Padrão e escolha Nenhum. Você verá esse valor, noone, na
coluna Padrão.
Em seguida, adicione um evento a obj_par_environment: clique em Adicionar evento e escolha Criar evento.
Neste novo Create Event, escreva o seguinte código:
// Variáveis do emissor
meuEmissor = 0;
// Cria emissor
if (useSound != noone) {
if !audio_is_playing(useSound) {
meuEmissor = audio_emitter_create();
audio_emitter_position(meuEmissor,x,y,0);
audio_falloff_set_model(audio_falloff_exponent_distance);
audio_emitter_falloff(meuEmissor,fallStart,maxDist,1);
audio_play_sound_on(myEmitter,useSound,1,1);
}
}
Aqui, estamos criando um Audio Emitter, armazenando seu ID na variável myEmitter e, em seguida, definindo várias
opções sobre como o som é tratado. As três principais coisas que você precisa prestar atenção são:
A próxima coisa que precisamos fazer para que isso funcione é escolher um som para obj_fountain tocar.
Abra obj_fountain e clique em Variable Definitions no Object Editor. Clique no ícone de lápis para desbloquear a
variável useSound que nossa fonte herdou de seu pai e, em seguida, clique no menu suspenso em Padrão. Escolha
snd_fountain.
A última coisa que precisamos fazer é garantir que nosso som de fonte seja compatível com a configuração de
áudio posicional 3D que criamos.
Abra snd_fountain no Navegador de recursos. No Sound Editor, em “Target Options”, certifique-se de definir a
“Output” para 3D.
Feito tudo isso, execute o jogo novamente e dê uma volta pela cidade; você deve ouvir aquela fonte
gloriosa borbulhando em um espaço 3D realista.
(Se você achar que a fonte está muito silenciosa quando estiver mais longe, você pode abrir obj_fountain e
editar as definições de variáveis para fallStart e maxDistance.)
Agora temos uma cidade florescente com três personagens, áudio 3D e um personagem principal tagarela.
Na próxima sessão, vamos lidar com caixas de texto e criar objetos em tempo real. Não se esqueça de
salvar seu projeto!
6 Sessão 3
Nesta sessão, colocaremos nossos três personagens (o padeiro, o professor e a mercearia) conversando
com caixas de texto e introduziremos alguns elementos da interface do usuário (IU) em nosso jogo.
Usando o File Explorer (Windows) ou o Finder (Mac), navegue até a pasta Ativos fornecida com este curso.
Encontre a pasta chamada User Interface e arraste esses Sprites para o GameMaker Studio 2:
• spr_gui_prompt
• spr_gui_textbox
No Asset Browser, crie um novo grupo no grupo Sprites chamado User Interface.
Crie um novo objeto e nomeie-o como obj_textbox. No Object Editor, anexe o Sprite spr_gui_textbox
que acabamos de importar.
Em seguida, clique em Adicionar evento e adicione Criar evento. Neste novo evento, vamos inserir uma variável básica
para começar:
Este é o texto que teremos em nossa caixa de texto. Escreva o que quiser aqui, mas não demore muito.
Dica: Se você vir um ícone em uma linha de código como esta, isso
significa que você criou uma variável que não usou em nenhum outro
lugar. Isso é normal neste momento.
Agora vamos fazer algo novo: fazer com que nossa caixa de texto exiba algumas coisas de uma só vez usando
o que chamamos de Draw Event.
No Object Editor para obj_textbox, clique em Add Event e passe o mouse sobre Draw — você notará várias
opções aqui, mas, por enquanto, apenas escolha aquela simplesmente chamada Draw.
desenhe_self();
// Desenha o Texto
draw_text(x,y,textToShow);
Quando você anexa um Sprite a um Objeto, esse Objeto o desenha automaticamente, mesmo sem um Evento Desenhar. Adicionar um
Draw Event substitui esse comportamento automático, então agora devemos dizer ao GameMaker Studio 2 que ainda
queremos que nosso objeto de caixa de texto desenhe o Sprite que anexamos.
Aqui, draw_self() faz exatamente isso. Podemos ficar muito mais sofisticados ao desenhar Sprites, mas, por enquanto, isso basta.
Em seguida, draw_text também faz o que diz: desenha uma string de texto (que pode ser uma letra, um número, uma palavra,
uma frase etc.) e o faz em uma coordenada x e y específica. (Lembre-se: apenas colocar x e y significa: “desenhe isso na minha
posição x e y”.)
Ok, vamos ver o que fizemos até agora. Abra rm_gameMain e certifique-se de clicar na camada Instances. Arraste uma instância
de obj_textbox para a Sala, onde quiser.
Nosso novo obj_textbox, posicionado dentro da cidade do jogo. Não é bem isso que queremos.
Você notará que isso não é exatamente o que esperávamos. No entanto, embora o texto possa ser muito difícil de ler (e pode parecer
diferente dependendo do seu sistema), nosso objeto de caixa de texto é
desenhando corretamente tanto a caixa de texto Sprite quanto o texto que escrevemos, então isso é uma vantagem.
Para fazer com que nossa caixa de texto se comporte da maneira que deveria, precisamos ser mais específicos sobre como
queremos que nosso texto apareça e o que acontece com ele.
No Navegador de recursos, clique com o botão direito do mouse no grupo Fontes e escolha Criar > Fonte. O editor de fontes do GameMaker
Clique ao lado de Select Font e escolha qualquer fonte disponível em seu sistema que você goste.
Não precisamos nos preocupar com a maioria das opções aqui, mas certifique-se de que “Anti-aliasing” esteja ativado; isso garantirá que
sua fonte seja suavizada corretamente e tenha uma boa aparência, independentemente do tamanho. Apontar para um tamanho de fonte
Dica: se você criar uma fonte a partir de um tipo de letra que pode ser
removido do seu sistema, isso poderá causar problemas posteriormente. É
uma boa ideia instalar fontes especiais que você planeja usar ou usar um
software de gerenciamento de fontes para garantir que elas sejam
ativadas quando você estiver trabalhando em seu projeto.
Quando estiver satisfeito com sua nova fonte, abra obj_textbox novamente e seu Draw Event. Vamos enfeitar esse texto.
Atualize o bloco de código // Draw Text da seguinte forma:
// Desenha o Texto
draw_set_font(font_textbox);
draw_set_color(c_black);
draw_set_halign(fa_center);
draw_set_valign(fa_middle);
draw_text(x,y,textToShow);
Uma última coisa: abra spr_gui_textbox novamente no Asset Browser e certifique-se de que a Origem para este Sprite esteja no
meio. Uma maneira fácil de fazer isso no Sprite Editor é clicar no menu suspenso na parte superior da janela ao lado de
Origin e escolher Middle Center.
Quando terminar, abra rm_gameMain novamente e certifique-se de que a caixa de texto Object esteja posicionada para que
você possa vê-la claramente.
Em seguida, execute o jogo novamente e dê uma olhada em nossa caixa de texto atualizada. Embora ainda não esteja certo,
deve ficar melhor com texto preto que você pode ler sobre a caixa de texto Sprite:
Dependendo do texto que você colocou na variável textToShow, seu texto pode ter saído da caixa de texto (como o
nosso). Isso porque a função simples que estamos usando (draw_text()) não tem muitas opções e não leva em
consideração detalhes como largura máxima.
Mas o GameMaker Studio 2 possui várias funções de desenho de texto; então, vamos substituir nosso código
draw_text simples por algo um pouco mais flexível.
Primeiro, abra obj_textbox e seu evento Create. Atualize o // bloco de código de variáveis de caixa de texto da
seguinte forma:
Em seguida, abra o evento Draw de obj_textbox. Atualize o bloco de código de texto // Draw novamente, assim:
// Desenha o Texto
draw_set_font(font_textbox);
draw_set_halign(fa_center);
draw_set_valign(fa_middle);
draw_text_ext_color(x,y,textToShow,lineHeight,textWidth,c_black,c_black,c_black,c_
preto,1);
Você notará que não temos mais a linha de código que define a cor. Essa nova função
draw_text_ext_color() nos permite fazer várias coisas em uma linha, incluindo definir a cor do texto que
estamos desenhando. (Podemos definir quatro cores aqui, então fique à vontade para brincar e ver o que
acontece!)
Você pode ler mais detalhes sobre o que a função draw_text_ext_color() faz no manual do
GameMaker Studio 2, mas os três novos argumentos que você vê aqui (lineHeight e textWidth, que
definimos no Create Event, e o 1 no final) são para entrelinhas (espaço entre as linhas), largura máxima
(para manter o texto dentro do nosso Sprite) e alpha (transparência ) , respectivamente .
Execute o jogo novamente para ver como a caixa de texto está agora. Se não estiver certo, você pode
ajustar as variáveis que definimos no Create Event do obj_textbox. Você também pode alterar o
valor de textToShow para testar um bloco maior de texto.
Nosso objeto textbox com mais texto e com entrelinhas (espaço entre linhas) e uma largura máxima aplicada.
Nossa caixa de texto parece organizada, mas deixá-la parada na cidade não é muito útil. Além do mais, dependendo de
onde você o colocou na Sala, ele pode estar atrás de alguns Objetos, o que não é o que queremos.
Então, vamos aprender como podemos criar uma caixa de texto quando precisamos dela (por exemplo, quando nos
aproximamos de um NPC) e como podemos alterar o texto que ela exibe.
Primeiro, volte para rm_gameMain e exclua a instância da caixa de texto que você arrastou para a cidade; não vamos mais
precisar disso aqui.
Em seguida, abra obj_player. Codificamos todos os tipos de funcionalidade no Step do nosso player
Evento até agora, mas vamos tentar algo novo.
Clique em Adicionar evento e escolha Pressionar tecla > Espaço. Este é um evento especificamente para quando a tecla
de espaço é pressionada pela primeira vez.
Adicionando um pressionamento de tecla – evento de espaço a obj_player, com código para criar uma caixa de texto
Observe que a função aqui é instance_create_depth, o que significa que estamos criando uma instância de Object em
uma determinada profundidade. Também podemos criar instâncias em camadas específicas em uma Room (com
instance_create_layer), desde que essa camada exista.
Feito isso, execute o jogo novamente e pressione a tecla de espaço para ver o que acontece. Voilá!
caixa de texto no comando.
Então, e se quisermos criar uma caixa de texto apenas quando estivermos perto do Padeiro, Professor ou Merceeiro?
Bem, abra obj_player e olhe em seu Step Event. Já temos uma maneira de verificar isso, não temos? É aquela variável
que criamos chamada nearNPC, dentro do bloco de código // Verificar colisão com NPCs.
Então, abra o Key Press - Space Event do obj_player e atualize o // Create a textbox
bloco de código assim:
Agora execute o jogo novamente e teste-o; você não deve conseguir criar uma caixa de texto com a tecla
Espaço, a menos que esteja perto de um dos três caracteres.
A criação de uma caixa de texto agora só pode ocorrer quando o Objeto do jogador detecta um NPC.
Feche a janela do jogo e retorne ao GameMaker Studio 2. Queremos que cada um de nossos três
personagens diga algo diferente quando o jogador se aproximar deles; para fazer isso, vamos usar as
definições de variáveis novamente e apresentar um novo recurso do GameMaker Studio 2.
Primeiro, abra obj_par_npc e clique em Variable Definitions novamente. Atualmente, temos apenas as
variáveis loopRange01 e loopRange02 aqui.
Clique em Adicionar e adicione uma nova definição. Nomeie-o como myText, defina seu Type como
String e digite "Ora, olá!" em Default (com aspas).
Abra mais uma vez o objeto obj_player e abra seu Key Press - Space Event. Aqui, escrevemos o código para criar uma
instância de obj_textbox. Agora, porém, vamos fazer algo um pouco mais.
No topo do Event, antes do // Create a textbox if NPC is near near code block, adicione esta linha:
var _texto;
(Aqui, estamos criando uma nova variável, _text, mas não atribuindo nenhum valor a ela ainda. Faremos isso de
maneiras diferentes ao longo desta sessão, então só queremos tê-la pronta agora.)
Em seguida, atualize o bloco de código // Criar uma caixa de texto se o NPC estiver próximo da seguinte forma:
Atualizando o evento Key Press – Space para obj_player para informar a uma caixa de texto qual texto exibir.
Você pode ver que fizemos algo com essa nova variável _text:
Você pode ler esta linha como: “pegue o valor de myText no NPC próximo (que é o personagem ao lado do qual
estamos) e armazene-o em _text.
iii = instance_create_depth(nearbyNPC.x,nearbyNPC.y-400,-10000,obj_textbox);
Nesta linha de código atualizada, estamos armazenando o ID da instância da caixa de texto que estamos criando
na variável iii. Então, na nova linha abaixo dela, estamos fazendo algo legal: passando uma variável de uma
instância para outra!
iii.textToShow = _text;
Estamos dizendo: “naquela nova caixa de texto que acabamos de criar (iii), defina o valor da variável
textToShow para ser o mesmo que tudo o que armazenamos aqui em _text”.
Feito isso, execute o jogo novamente e caminhe até um dos três NPCs. Pressione a tecla de espaço e esse NPC
deve dizer "Ora, olá!" em vez do que disse antes.
Agora nossa caixa de texto exibe corretamente o texto que foi passado para ela.
Finalmente, vamos garantir que cada um de nossos três personagens diga algo diferente. Feche
a janela do jogo e retorne ao GameMaker Studio 2.
Todos os nossos três NPCs têm seus próprios diálogos agora, o que é ótimo. No entanto, há mais algumas coisas que
precisamos fazer para que a caixa de texto faça sentido:
• Quando uma caixa de texto está ativa, o jogador não pode se mover (isso seria grosseiro)
• A caixa de texto deve desaparecer quando o jogador pressionar a tecla de espaço novamente
Uma maneira fácil de permitir e proibir o controle do jogador em situações é a mesma que fizemos com o controle quando
nosso jogador diz “olá”: crie uma variável e defina-a como verdadeira quando quiser que o jogador tenha controle e defina-a
como falsa quando não quiser.
Abra obj_control e no Object Editor, clique em Add Event. Escolha Outro > Início do jogo.
Este é um evento especial que (como você deve ter adivinhado) ocorre quando o jogo começa. Um Objeto que usa este
Evento deve ser colocado na primeira Sala do seu jogo e o Objeto deve ser colocado no Editor de Sala.
No novo evento de início do jogo, adicione este novo bloco de código ao final do evento:
// Variáveis do jogo
global.playerControl = verdadeiro;
Isso é chamado de variável global . Funciona da mesma forma que qualquer outra variável, exceto que cada Objeto no jogo
pode procurá-la e alterá-la.
Agora abra obj_player e seu Step Event e edite o // Check keys for motion code block para que fique assim:
Estamos apenas implementando a nova variável global.playerControl. Se for verdade, o jogador pode se mover
normalmente. Se não for, tiramos o controle.
Em seguida, vá para Key Press - Space Event de obj_player e edite // Create a textbox if
O NPC está próximo do bloco de código da seguinte forma:
O que fizemos foi alterar a primeira instrução if para incluir uma verificação de
global.playerControl. Faz sentido, certo? Se não pudermos nos mover quando o controle do jogador for retirado,
também não poderemos pressionar a barra de espaço para fazer as coisas.
Finalmente, abra obj_textbox novamente. Em seu Create Event, adicione esta linha ao bloco de código //
Textbox variables:
global.playerControl = false;
Toda vez que criamos um objeto de caixa de texto, tiramos o controle do jogador; isso resolve nosso primeiro
problema. Mas o que fazemos para recuperá-lo?
Vamos resolver nosso segundo problema; para fechar a caixa de texto quando o jogador pressionar espaço
novamente e permitir que o jogador se mova mais uma vez.
Certifique-se de ter obj_textbox aberto e clique em Add Event no Object Editor. Adicione um evento Key Press -
Space e escreva o seguinte código neste evento:
Em seguida, adicione outro Evento: Alarme > Alarme 0. Neste novo Evento de Alarme, escreva o seguinte:
// Destrua-me
global.playerControl = verdadeiro;
instância_destroy();
Instance_destroy() é uma função poderosa que, por padrão, destrói a instância que a chama
(você também pode segmentar outras instâncias em uma sala). E embora o código escrito em um evento após
instance_destroy() é usado ainda pode ser executado tecnicamente, é uma boa ideia não fazê-lo. (Você pode ler mais
no manual do GameMaker Studio 2.)
Portanto, com esta configuração, estamos acionando o Alarme 0 apenas 2 etapas após pressionarmos a tecla de
espaço. Por que estamos usando um alarme para fazer isso? Não deveríamos ser capazes de fechar a caixa de texto
dentro do próprio Key Press - Space Event?
Bem, você pensaria assim, mas esta é uma daquelas peculiaridades da programação. Veja bem, pressionar a
tecla de espaço quando o jogador tem o controle (no obj_player) e pressioná-la quando o jogador não tem o controle (no
obj_textbox) pode acontecer ao mesmo tempo! Então, só para garantir, estamos fazendo dessa maneira.
De qualquer forma, depois de fazer tudo isso, execute o jogo novamente e fale com cada um dos três
personagens. Você deve observar que:
Testando nossa caixa de texto atualizada, que agora removerá o controle do player e pode ser fechada
pressionando a barra de espaço.
Depois de verificar tudo, feche a janela do jogo e retorne ao GameMaker Studio. Certifique-se de salvar seu projeto
e vamos seguir em frente!
No momento, nossa caixa de texto apenas aparece e desaparece quando a invocamos, o que é um pouco monótono. Que
tal animá-lo um pouco e fazer com que apareça e desapareça?
Abra obj_textbox novamente e seu Create Event. Adicione estas novas linhas ao bloco de código // Textbox variables:
fadeMe = 0;
fadeSpeed = 0,1;
imagem_alfa = 0;
Vamos usar essas variáveis para controlar como a caixa aparece e desaparece gradualmente. Observe que
image_alpha é uma variável interna para definir a transparência (0 é completamente transparente e 1 é
completamente opaco). Ao definir isso aqui como 0, iniciamos a caixa de texto como invisível, para que possamos
esmagá-la gradualmente.
Em seguida, no Object Editor, clique em Add Event e adicione um Step Event regular. Neste evento, adicione todo este
bloco de código, que contém uma instrução switch:
// Efeitos de fade
alternar fadeMe {
// Aparecimento gradual
caso 0: {
if (imagem_alfa < 1) {
image_alpha += fadeSpeed;
}
if (image_alpha == 1) {
fadeMe = 1;
}
}; quebrar;
// Desaparecer
caso 2: {
if (imagem_alfa > 0) {
image_alpha -= fadeSpeed;
}
if (image_alpha == 0) {
fadeMe = 3;
// Coloca na fila destrói
alarme[0] = 2;
}
}; quebrar;
}
Vamos detalhar algumas coisas aqui: já escrevemos instruções switch antes e esta não é diferente. Então, aqui
estamos dizendo, "se fadeMe for 0 e meu image_alpha for menor que 1, aumente meu image_alpha em uma quantidade
específica a cada passo" (usando fadeSpeed, que definimos no Create
Evento). Em seguida, “quando image_alpha atingir 1, defina fadeMe como 1 para parar”.
O próximo caso, 2, faz o oposto. Ele também define o Alarme que criamos antes — aquele que destrói a caixa de
texto. Então, como definimos fadeMe como 2 para que este caso seja executado?
Abra o Key Press de obj_textbox - Evento Espacial. Aqui, definimos anteriormente o Alarme 0 se
pressionássemos a barra de espaço. Mas não precisamos mais disso, pois o Step Event cuida disso.
Então, vamos substituir todo o bloco de código // Fila minha destruição por isto:
// Começa a desaparecer
if (fadeMe == 1) {
fadeMe = 2;
}
/*
//// Código antigo
// Fila minha destruição
alarme[0] = 2;
*/
Em vez de destruir imediatamente o objeto textbox, estamos configurando o efeito “fade out” que acabamos de
escrever no Step Event. Perfeito!
Uma última coisa: abra o evento Draw de obj_textbox e faça uma pequena edição na linha
draw_text_ext_color() no bloco // Draw text code:
// Desenha o Texto
draw_set_font(font_textbox);
draw_set_halign(fa_center);
draw_set_valign(fa_middle);
draw_text_ext_color(x,y,textToShow,lineHeight,textWidth,c_black,c_black,c_black,c_
preto, imagem_alfa);
Tudo o que você está fazendo aqui é alterar o último valor, 1, para image_alpha. Isso é feito para que o texto também
respeite o efeito de fade que acabamos de codificar.
Execute o jogo novamente e caminhe até qualquer NPC e pressione a tecla de espaço. Meu Deus, é lindo!
Dica: se você quiser alterar a velocidade com que a caixa de texto aparece
e desaparece, basta alterar o valor de fadeSpeed.
Para completar nossa caixa de texto, vamos garantir que ela reproduza um efeito sonoro quando for aberta.
audio_play_sound(snd_pop01,1,0);
Esta é a mesma função de som que usamos em obj_control para reproduzir nossa música de fundo e ambiente. A única
diferença aqui é o último número (0), que é para o argumento do loop.
Ao definir isso como 0, o som será reproduzido apenas uma vez.
Execute o jogo novamente para testar a caixa de texto mais uma vez; quando ele aparecer, você deve ouvi-lo
estourar!
Normalmente em um jogo, se um jogador pode realizar uma ação (como falar com um NPC), existe algum tipo de elemento
de interface do usuário (UI) que permite que eles saibam de antemão.
Então, em nosso jogo, teremos uma pequena bolha aparecendo quando estivermos dentro do alcance de nossos NPCs que
nos permite saber que podemos falar com eles.
Já importamos o Sprite para este novo elemento, então vamos abri-lo agora no Asset Browser: chama-se spr_gui_prompt.
Faça o ponto de origem para este Sprite Middle Center e então feche o Sprite Editor.
No Object Editor, anexe spr_gui_prompt e feche o Object. (Faremos mais com este objeto mais tarde,
mas, por enquanto, só precisamos que ele exista e tenha um Sprite.)
O novo obj_prompt ainda não precisa de nenhum evento; ele só precisa existir.
Às vezes, no GameMaker Studio 2, você deseja escrever código para fazer exatamente a mesma coisa em
momentos diferentes ou por motivos diferentes (como exibir um prompt para informar ao jogador que há
algo interessante à sua frente).
Em vez de sempre escrever um bloco de código e copiá-lo e colá-lo onde for necessário, podemos criar nossas
próprias funções e armazená-las em Script Assets.
Esses Script Assets tornam-se parte do próprio projeto e as funções que eles contêm se comportam exatamente
como as funções incorporadas ao GameMaker Studio 2.
Vamos criar um Script Asset para algumas novas funções — a primeira será para exibir aquele objeto de
prompt que acabamos de criar. À medida que continuamos no curso, você verá que o reutilizaremos em alguns
lugares diferentes.
No Navegador de ativos, clique com o botão direito do mouse e escolha Criar > Script. Nomeie este novo
Script como scr_promptControl e arraste-o para o Grupo de Scripts para proteção.
Você verá que o GameMaker Studio 2 abriu o Script, que incluirá isso por padrão:
função scr_promptControl(){
Isso pode parecer um pouco confuso no início, mas o GameMaker Studio 2 criou um Script
Asset e uma função dentro desse Script Asset com o mesmo nome.
Por padrão, o GameMaker Studio 2 cria uma função dentro de um novo recurso Script com o mesmo nome.
No entanto, queremos que nossa primeira função tenha um nome diferente, então atualize o bloco de código da seguinte forma:
função scr_showPrompt(){
Você está pronto para se sentir um desenvolvedor superpoderoso? Porque vamos escrever nossa primeira função!
(Spoiler: é bem fácil.)
Já tivemos muita experiência com funções — especificamente, funções de tempo de execução, que são as funções
integradas que o GameMaker Studio 2 já possui, como instance_create_depth().
E assim como essas, podemos criar uma função bem simples ou com muitas opções.
function scr_showPrompt(_object,_x,_y) {
if (instance_exists(_object)) {
if (!instance_exists(obj_textbox) && !instance_exists(obj_prompt)) {
iii = instance_create_depth(_x,_y,-10000,obj_prompt);
retornar iii;
}
}
}
Este é principalmente o código que escrevemos antes: aqui, estamos nos certificando de que uma caixa de texto não
exista e que uma instância do prompt Object que desejamos exibir ainda não exista.
Se ambas as coisas forem verdadeiras, estamos criando uma instância do prompt em um determinado ponto e em uma
profundidade que o colocará próximo à câmera. (Isto é exatamente como o código que escrevemos em Dando voz
própria aos nossos NPCs.)
No entanto, parece que há uma nova reviravolta. O que são _object, _x e _y? Conforme abordamos em Alterando todos
os nossos eventos de movimento para o código, eles são chamados de argumentos — parâmetros que uma função precisa
para funcionar.
É como pedir o almoço: você pode pedir um sanduíche, mas seu garçom vai perguntar qual sanduíche, que tipo de pão
você quer e se quer picles nele?
Se esta transação de exemplo fosse uma função, ela poderia se parecer com isto:
scr_orderSandwich(_whatKind,_whichBread,_pickles);
Se não dermos todas essas informações ao servidor, eles não poderão processar nosso pedido e não receberemos nosso
sanduíche.
Para nossa função scr_showPrompt(), estamos fazendo três perguntas; para qual objeto nosso jogador está olhando
(_object), em qual posição x (_x) e posição y (_y) devemos criar um objeto de prompt?
Você também pode ver que estamos usando outra linha iii = algo aqui. É assim que armazenamos o ID de instância exclusivo
do objeto de prompt que criamos para uso posterior. Mas abaixo disso você verá algo novo:
retornar iii;
Em uma função, você pode, digamos, fazer um monte de matemática e retornar o resultado de toda essa matemática no final.
Isso permite que qualquer objeto que tenha executado a função em primeiro lugar pegue esse resultado e faça
algo com ele.
Aqui estamos retornando o ID de instância exclusivo do obj_prompt que criamos. Se não fizermos isso, nosso Objeto
jogador não terá ideia do que seja (mesmo que vá executar a função).
Dica: uma função termina com uma linha de retorno. Qualquer código após
essa linha não será executado.
Vamos implementar essa nova função para entendermos como tudo funciona.
Abra o obj_player e seu Create Event; precisamos adicionar uma nova variável, então adicione uma nova linha ao bloco de
código // Variables:
npcPrompt = ninguém;
nearbyNPC { //
Redefinir saudação if
(hasGreeted == true)
{ hasGreeted = false; }
Esperançosamente, isso faz mais sentido agora: queremos criar uma instância de obj_prompt em
uma posição x e y específica, mas queremos fazê-lo com base em um NPC ao lado do qual estamos.
Quando uma função retorna um resultado, esse resultado pode ser armazenado em uma variável
usando o mesmo someVariable = fancyFunction(); técnica que mencionamos antes.
Execute o jogo e caminhe até um dos três personagens. Ao chegar dentro do alcance, você deve ver nosso
prompt aparecer. Viva!
Testando para confirmar que obj_prompt aparece acima de nossos NPCs quando o objeto do jogador está próximo.
Claro, você pode notar que nosso prompt tem alguns problemas. Ainda precisamos:
Vamos resolver os dois primeiros problemas. Vamos editar obj_prompt para ter um sistema de fade semelhante ao
obj_textbox e dar a ele um efeito sonoro simples.
Abra obj_prompt no Editor de objetos. Clique em Adicionar evento e adicione Criar evento. Neste novo evento, escreva o
seguinte para começar:
// Variáveis de prompt
fadeMe = "fadeIn";
fadeSpeed = 0,1;
imagem_alfa = 0;
Como você pode ver, estamos usando algumas variáveis simples aqui da mesma forma que fizemos em obj_textbox.
Mas o que há com essa variável fadeMe? Vamos explicar isso momentaneamente.
// Toca o som da
interface do usuário audio_play_sound(snd_pop02,1,0);
Assim como fizemos com a caixa de texto, agora adicionamos um efeito sonoro simples ao prompt.
Agora, no Object Editor, clique em Add Event novamente e adicione um Step Event. Nele, adicione o seguinte
bloco de código:
// Interruptor de
efeitos de fade fadeMe {
// Fade in
case "fadeIn": { if
(image_alpha < 1)
{ image_alpha += fadeSpeed; }
if (imagem_alfa >= 1) {
fadeMe = "fadeVisible"; } };
quebrar;
// Fade out
case "fadeOut": { if
(image_alpha > 0)
{ image_alpha -= fadeSpeed; }
Este é essencialmente o mesmo código que estava em obj_textbox. No entanto, há uma diferença importante:
aqui, em vez de usar números como valores para nossa variável fadeMe, usamos texto (uma string, lembre-se).
Portanto, em vez de 0, 1 e 2, temos rótulos fáceis de ler, como fadeIn, fadeVisible e fadeOut.
Por que fizemos isso e não usamos números como fizemos com obj_textbox?
Não há nenhum truque secreto aqui: isso é apenas para demonstrar a flexibilidade que você tem com as
variáveis e seus valores. No que diz respeito ao GameMaker Studio 2, qualquer solução é boa, então
experimente o que faz sentido para você.
Dica: usar strings de texto para valores como esse facilita a leitura,
mas também pode facilitar erros. Se você digitar incorretamente um
valor para fadeMe ao verificar ou configurá-lo, seu código não
funcionará, então tome cuidado!
Para completar nosso efeito fade, precisamos adicionar um Alarm, assim como fizemos com obj_textbox;
você pode ver no código que acabamos de escrever no Step Event que o Alarm 0 está sendo
chamado no caso fadeOut. Vamos tentar algo novo para fazer isso rapidamente!
Abra obj_prompt novamente e no Object Editor, clique com o botão direito do mouse em um espaço em
branco na janela Events. Escolha Colar evento e pronto! — você pode facilmente copiar e colar
eventos em objetos.
global.playerControl = verdadeiro;
Não precisamos disso no obj_prompt, pois não é para remover o controle do player.
Feito isso, execute o jogo novamente e caminhe até um dos personagens. Você deve ver o prompt Object
desaparecer quando você se aproximar.
Testando nosso prompt novamente; agora deve desaparecer bem em vez de aparecer repentinamente.
As coisas estão ótimas agora, mas ainda precisamos resolver o segundo e o terceiro problemas e garantir que nosso
prompt desapareça quando nos afastarmos de um personagem ou quando uma caixa de texto aparecer.
Vamos lidar com isso com outra função dentro desse recurso de script scr_promptControl, portanto, sempre
que quisermos nos livrar de obj_prompt, podemos.
função scr_dismissPrompt(){
function scr_dismissPrompt(_whichPrompt,_toReset) {
if (_whichPrompt != indefinido) {
if (instance_exists(_whichPrompt)) {
// Diz ao prompt Object para desaparecer
com (_whichPrompt) {
fadeMe = "fadeOut";
}
// Redefine a variável de prompt apropriada
if (instance_exists(obj_player)) {
com (obj_player) {
alterne _paraRedefinir {
// Reinicializa npcPrompt
caso 0: npcPrompt = ninguém; quebrar;
}
}
}
}
}
}
Esta função tem dois argumentos: _whichPrompt e _toReset. O segundo argumento pode parecer
redundante agora, mas vamos precisar dele na próxima sessão. Você verá que temos uma instrução switch
dentro da função, embora ela tenha apenas um caso. Vamos expandir isso mais tarde.
Agora, vamos usar nossa nova função para resolver nosso segundo e terceiro problemas. Abra obj_player
e seu Step Event. Procure no bloco de código // Verificar colisão com NPCs o
Bloco de código !nearbyNPC e atualize-o assim:
se !próximo NPC {
// Reinicia saudação
if (cumprimentou == verdadeiro) {
cumprimentou = false;
}
// Livra-se do prompt
scr_dismissPrompt(npcPrompt,0);
Você pode ver que estamos usando a variável npcPrompt que obtemos de nosso scr_showPrompt()
função; é assim que direcionamos a instância exata do objeto prompt que criamos lá.
Em seguida, abra obj_textbox e seu Create Event. Após o bloco de código // Textbox variables, adicione este código:
(Observe que aqui não estamos visando nenhuma instância específica de obj_prompt, mas qualquer uma que esteja aberta, pois
obj_textbox não sabe o que nosso player está fazendo.)
Execute o jogo novamente, caminhe até um dos personagens e afaste-se. O prompt deve aparecer corretamente quando você
estiver por perto e desaparecer quando não estiver.
Teste novamente pressionando a barra de espaço para abrir uma caixa de texto; ele deve desaparecer quando a caixa de
texto aparecer e reaparecer quando você pressionar Espaço para fechar a caixa de texto.
Agora, graças à nossa pequena função, podemos nos livrar desse prompt a qualquer momento, com apenas uma linha de código!
Vamos fazer uma última coisa antes de terminar esta sessão. Apenas para adicionar um pouco de entusiasmo ao nosso
objeto de prompt, vamos torná-lo animado. Vamos fazê-lo balançar para cima e para baixo para realmente chamar a
atenção do jogador.
Abra obj_prompt e seu Create Event. Adicione as seguintes linhas de código após o bloco de código // Play UI sound:
alarme[1] = 10;
Em seguida, no Object Editor, clique em Add Event e escolha Alarm > Alarm 1. Neste novo evento, adicione este bloco de código:
alarme[1] = 10;
Finalmente, abra o Step Event do obj_prompt e adicione este código no topo do Event, antes do //
Bloco de código de efeitos de fade:
Esta é outra maneira de usar Alarmes para fazer algo divertido. A cada 10 passos, o Alarme 1 dispara, invertendo
o valor do shift (de 1 para -1, de volta para 1 e assim por diante). O obj_prompt estará constantemente
ajustando seu valor y por qualquer deslocamento, então ele se moverá para baixo, depois para cima, depois para baixo
e assim por diante, criando um efeito de oscilação simples.
Execute o jogo novamente e aproxime-se de um NPC. Agora, quando o prompt aparece, ele sobe e desce. Sinta-se à
vontade para brincar com os valores de mudança e alarme 1 para ver o que acontece.
É isso para esta sessão. No próximo, vamos fazer itens que podemos levar e muito mais.
Não se esqueça de salvar seu projeto!
7 Sessão 4
Nesta sessão, vamos fazer Objetos que podemos pegar e trazer para nossos três personagens.
Faremos com que o objeto do jogador saiba qual item está carregando e nos permita derrubar um item que não queremos.
Também vamos adicionar a capacidade de nosso jogador correr e fazer com que o peso de cada objeto afete sua velocidade.
Ao fazer isso, também aprenderemos sobre novas estruturas de dados e técnicas para manter nosso código gerenciável.
Teremos seis itens diferentes em nossa cidade para o jogador pegar, com seus próprios Sprites, nomes e valores. Portanto,
vamos desenvolver o que fizemos em Object parenting para facilitar a edição e criar um Object pai.
No Navegador de ativos, clique com o botão direito do mouse e escolha Criar > Objeto. Nomeie este novo Objeto
obj_par_item.
Abra obj_par_item se ainda não estiver aberto e clique em "Adicionar evento" e crie uma etapa regular
Evento. Como fizemos algumas vezes antes, basta adicionar uma linha de código para lidar com a classificação em profundidade:
// Classificação de profundidade
profundidade =-y;
Vamos adicionar algumas definições de variáveis ao nosso item pai que usaremos um pouco mais tarde na sessão.
No Editor de objetos, clique em Definições de variáveis e depois em Adicionar.
Nomeie esta primeira variável como itemName, mude seu Type para String e digite “nothing” (com
aspas) como seu valor padrão.
Adicione uma segunda variável; nomeie-o itemWeight, certifique-se de que seu Tipo seja Real e altere seu valor Padrão
para 2.
Usando o File Explorer (Windows) ou o Finder (Mac), navegue até a pasta Assets fornecida com este curso e abra a pasta
Sprites > Characters and Items. Você verá seis itens Sprites nomeados:
• spr_item01
• spr_item02
• spr_item03
• spr_item04
• spr_item05
• spr_item06
Arraste todos os seis desses Sprites para o navegador de recursos do GameMaker Studio 2. Para manter as coisas
organizadas, clique com o botão direito do mouse no Navegador de ativos e escolha Criar grupo; crie um novo grupo para
esses Sprites (chamados de Itens) e arraste esse grupo para dentro do grupo de Sprites pré-existente.
Como fizemos antes, abra cada um desses seis novos Sprites e ajuste seus pontos de origem e
máscaras de colisão, assim:
Quando terminar, clique com o botão direito do mouse no Navegador de recursos novamente e crie um novo Objeto. Chame-
o de obj_item01.
No Editor de objeto para este novo objeto, clique em Pai e clique no menu suspenso que diz "nenhum". Escolha o objeto que
acabamos de criar, obj_par_item, para que nosso novo objeto objeto se torne seu filho.
Substitua o valor padrão por “Rolling Pin”. (Você pode deixar a variável itemWeight como está por enquanto.)
Por fim, abra rm_gameMain e verifique se a camada Instances está selecionada no Room Editor.
Arraste uma instância de obj_item01 para o Room.
Execute seu jogo e faça com que seu jogador caminhe sobre o item para garantir que ele se comporte corretamente
em termos de profundidade. Caso contrário, pode ser necessário abrir seu Sprite novamente para ajustar seu ponto de
origem.
O que queremos fazer a seguir é permitir que o Objeto do jogador reconheça quando está parado ao lado de um item e
mostre um pequeno aviso. Felizmente, já fizemos isso com nossos NPCs (em Collisions), então deve ser fácil.
Primeiro, abra obj_player e seu Create Event. Adicione as seguintes linhas ao bloco de código // Variables para criar
algumas variáveis que vamos precisar:
hasItem = ninguém;
temItemX = x;
hasItemY = y;
nearItem = ninguém;
itemPrompt = ninguém;
carryLimit = 0;
Nosso objeto de jogador tem uma grande coleção de variáveis em seu evento Create.
Em seguida, abra o evento Step do obj_player. Encontre todo // Verifique se há colisão com NPCs
bloco de código; vamos escrever uma quase duplicata desse bloco, mas alterá-lo para procurar
nosso novo item Objetos.
Você pode copiar e colar este bloco e editá-lo para corresponder ou pode escrevê-lo manualmente.
De qualquer forma, crie um novo bloco de código abaixo do bloco de código // Verificar colisão com
NPCs, assim:
Quando os objetos verificam a colisão uns dos outros, eles estão usando o que é chamadomáscaras de
colisão. Estes são “pontos quentes” invisíveis em cada Sprite no jogo.
Você notará que o Sprite agora tem uma caixa cinza escura ao seu redor. Este é (como o nome sugere)
omáscara de colisãopara o quadro atual do Sprite. Quando o objeto do nosso jogador está verificando
obj_par_envrionment,é isso que determina se encontrou algo ou não. Se a colisão
Cada Sprite pode ter sua própria máscara de colisão e cadaquadrode um Sprite também pode ter o seu! Mas
vamos manter isso simples. No momento, a máscara de colisão do Sprite abrange toda a imagem, mas não é
isso que queremos.
Em vez disso, queremos apenas que a máscara de colisão de nosso cano esteja em sua base. Como o jogador pode
andar na frente e atrás do cano, não faz sentido visualmente para o jogador colidir com ele se seus pés, digamos,
estiverem tocando o topo do cano.
Você notará que a Collision Mask cinza escuro mudou de um retângulo para uma elipse. Se você clicar nesta
forma, poderá ajustá-la. (Você também pode inserir números para os quatro vértices da Collision Mask na
parte inferior esquerda do Sprite Editor.)
A Collision Mask agora está corretamente ao redor do fundo do barril. Tudo bem se a máscara se estender além do
cano assim.
Execute o jogo novamente para testar a alteração. O jogador deve parar corretamente ao se mover
contra um barril, de qualquer direção.
Agora que temos um objeto pai para nossos detalhes ambientais (obj_par_environment)e que nosso Objeto de
jogador possa rastrear corretamente as colisões com ele, é hora de criar a variedade de Objetos que
precisaremos para projetar adequadamente nossa cidade.
Já criamos nosso objeto barril, mas agora vamos criar objetos para utilizar o restante desses Sprite de
ambiente que importamos na Sessão 1.
A configuração correta para cada um dos nossos novos objetos de ambiente: com obj_par_environment selecionado
como pai e com o Sprite correto anexado.
Você também vai querer abrir ospr_tree01Sprite e ajuste sua origem e máscara de colisão, como
fizemos comspr_barrel01.
No Sprite Editor, faça a origem na base do tronco da árvore. Abra a seção “Collision Mask”
à esquerda do editor e altere o modo de máscara paraManual;para Tipo escolha Elipse
(lenta).
Nome do objeto Sprite para anexar Tipo de máscara de colisão a ser usado
Consulte estas capturas de tela para obter detalhes sobre as recomendações de máscara de colisão e origem:
Ao criar os cinco objetos de cidade de que precisamos, você notará quespr_fountain01é um Sprite Strip, como
os usados para o nosso objeto de jogador.
(Se esta Sprite Strip não foi importada corretamente com vários quadros de animação, siga as etapas em
Convertendo um Sprite Strip manualmente para convertê-lo.)
Quando terminar, certifique-se de organizar seus novos Objetos em um grupo no Navegador de recursos para manter as
coisas organizadas. (Clique com o botão direito do mouse no Navegador de ativos e escolhaCriar grupo, em seguida,
renomeie-o para algo comoDetalhes da cidade.)
Temos uma variedade de objetos agora, então é hora de usá-los para projetar ainda mais nossa cidade e dar-lhe
alguma personalidade.
Arraste quantos desses novos objetos quiser para projetar sua cidade. (Recomendamos que você
coloque apenas três instâncias deobj_store01e uma instância deobj_fountain,no entanto.)
Se precisar, fique à vontade para reorganizar ou deletar os barris originais que você colocou na Sala (para
deletar uma Instância de uma Sala, clique nela e aperte Delete no seu teclado). Você também pode mover
obj_playerao redor também.
Dica:À medida que você move as instâncias pela sua sala, você notará que
elas estão se ajustando à grade na sala (a menos que você tenha
desativado isso). Se você quiser mover uma Instância sem que ela se
encaixe, segure Alt (Windows) ou Option (Mac) enquanto a arrasta.
Usando “Flip X” em uma instância de obj_rock01. Observe como “Escala X” agora é -1.
Se você quiser alguma variedade, pode ajustar uma instância individual de um objeto dentro de uma sala.
Clique duas vezes em qualquer Instância (por exemplo,obj_rock01)e você verá as Propriedades dessa Instância.
Há muitas opções aqui nas quais não entraremos agora, mas observe a chamada "Flip X". Se você
marcar isso, essa Instância específica será invertida horizontalmente.
Você também notará que, se verificarVirar X,a opção abaixo dela,Escala X,muda de1para -1. Se uma
InstânciaEscala XouEscala Yconfiguração é um número negativo, significa que foi invertido.
Um objeto de rocha bastante enorme. Você pode ver a escala exata da Instância em suas Propriedades (clique duas
vezes na Instância para abrir)
No entanto, embora seja recomendável inverter uma Instância para variar, dimensionar Instâncias dessa maneira
não é. (Mas ei, é a sua cidade!) Se quiser redefinir a escala de uma Instância, você pode alterar suaEscala XeEscala Y
configurações de volta para 1.
Se você quiser ajustar as telhas que você colocou, selecione oLadrilhos Principalcamada e clique na guia Room Editor
para ver o Tile Set que usamos novamente. Você pode remover ou alterar os blocos conforme necessário.
Depois de obter todos os seis objetos, abra rm_gameMain. Certifique-se de que a camada Instances esteja
selecionada no Room Editor e arraste uma instância de cada item para o Room. Coloque os itens onde
quiser por enquanto; para o jogo final, você vai querer esconder um pouco os itens, para que os jogadores
tenham que procurá-los.
Execute o jogo novamente e caminhe pela cidade. Pegue cada item e carregue-o e solte-o novamente.
Observe como os diferentes valores de peso do item que você definiu afetam a lentidão com que o jogador
se move enquanto os carrega. Sinta-se à vontade para ajustá-los, se necessário!
Nosso objeto de jogador está ficando bastante ativo agora, mas vamos dar um passo adiante. Abra obj_player
e seu Create Event e adicione as seguintes linhas ao bloco de código // Variables:
runSpeed = 0;
runMax = 12;
correndo = falso;
Agora, abra o Step Event do obj_player e adicione o seguinte entre os // Check keys for motion e // Calculate motion code
blocks:
Como estamos verificando a tecla Shift em Step e passando o resultado (true ou false) para a variável running, agora
temos uma maneira prática de detectar se nosso personagem está executando ou não.
Mas o que fazemos com isso? Por que, acelere o jogador, é claro!
Abaixo deste novo bloco de código // Executar com a tecla Shift, vamos adicionar um novo bloco para lidar com a
velocidade de execução do nosso player:
}
}
// Desacelera se não estiver mais rodando
if (em execução == falso) {
// Desaceleração
if (velocidade de execução > 0) {
velocidade de execução -= 1;
Em vez de alterar a velocidade imediatamente, estamos aumentando e diminuindo para fornecer uma sensação
de movimento mais realista.
Em seguida, devemos aplicar a velocidade ao objeto do jogador. Bem ali no Step Event do obj_player está o
bloco // Calculate motion que escrevemos e atualizamos antes. Vamos fazer mais uma alteração neste bloco,
assim:
// Calcula o movimento
vx = ((moveRight - moveLeft) * (walkSpeed+runSpeed) * (1-carryLimit));
vy = ((moveDown - moveUp) * (walkSpeed+runSpeed) * (1-carryLimit));
Adicionando o novo código de execução e atualizando o bloco de código // Calcular movimento, na etapa do obj_player
Evento
Mais uma vez, execute o jogo e mova o objeto do jogador. Tente manter pressionada a tecla Shift para observar o
jogador decolar e solte-a para vê-lo desacelerar novamente. Observe que você também pode correr carregando
um item, mas o peso de cada item continuará a afetar a velocidade do jogador.
Vamos adicionar um recurso final para esta sessão para tornar a travessia de nosso jogador pela cidade completa:
um efeito de nuvem de poeira de desenho animado que se arrasta atrás deles quando eles correm.
Primeiro, use o Explorer no Windows ou o Finder no Mac e navegue até a pasta Asset que acompanha este curso. Em
Characters and Items, você encontrará o arquivo de imagem spr_dust. Arraste-o para o navegador de recursos do
GameMaker Studio 2. (Recomendamos inseri-lo em Sprites > Player
Grupo.)
Abra spr_dust e clique no menu suspenso Origin no canto superior direito do Sprite Editor para definir a origem como
Middle Center. (Você não precisa se preocupar com a máscara de colisão para este ativo.)
Ajuste a origem para nosso novo Spr_dust Sprite e coloque o recurso no grupo Sprites > Player.
Em seguida, precisamos criar o Objeto de poeira; clique com o botão direito do mouse no Navegador de ativos e escolha
Criar > Objeto. Nomeie este novo objeto obj_dust.
Abra obj_dust no Editor de objetos. Clique em No Sprite e anexe o novo ativo spr_dust que acabamos de importar.
Em seguida, adicione um Create Event. Neste evento, adicione o seguinte bloco de código:
// Variáveis de poeira
image_xscale = random_range(0.8,1.2);
image_yscale = image_xscale;
rotSpeed = random_range(0.5,2);
fadeSpeed = random_range(0.025,0.05);
driftSpeed = random_range(1,5);
Ter todas as nuvens de poeira aparecendo exatamente do mesmo tamanho e fazendo exatamente a mesma coisa
não é realista. Para realmente vender o efeito, queremos dar a cada nuvem alguma variação de tamanho, velocidade
de rotação e muito mais.
Para alterar o tamanho, estamos definindo primeiro a image_xscale do objeto. Essa variável interna é, como você pode
imaginar, a escala de um Sprite em seu eixo x. Para manter a largura e a altura da nuvem de poeira proporcionais, estamos
definindo image_yscale para ser qualquer image_xscale.
Dica: Se você quiser permitir nuvens que não são proporcionais, então você
pode dar a image_yscale seu próprio intervalo aleatório.
As outras variáveis aqui também têm intervalos aleatórios para permitir variedade. Você pode alterar os números
nesses intervalos mais tarde para ver como isso afeta as coisas, mas, por enquanto, deixe-os assim.
Em seguida, adicione um Step Event ao nosso obj_dust no Object Editor. Dentro deste Step Event, escreva o seguinte:
// Gira a nuvem
image_angle += rotSpeed;
y -= driftSpeed;
// Desaparecer
if (imagem_alfa > 0) {
image_alpha -= fadeSpeed;
}
if (image_alpha <= 0) {
instância_destroy();
}
A variável incorporada image_angle nos permite definir a rotação do Sprite, mas como estamos constantemente
adicionando um valor (rotSpeed) a ele, ele continuará girando, criando um efeito giratório.
Da mesma forma, ao subtrair constantemente driftSpeed do valor y de obj_dust, ele continuará a se mover para cima,
criando um efeito crescente.
Finalmente, estamos fazendo a mesma coisa aqui com image_alpha que fizemos antes em seções como Adicionar efeitos à
nossa caixa de texto. Quando nosso image_alpha chega a 0, destruímos a nuvem de poeira. Como o fadeSpeed é
aleatório, cada nuvem se comportará de maneira um pouco diferente, dando-nos a variedade de que precisamos.
Para fazer isso, abra obj_player e seu Create Event novamente. Adicione uma nova variável ao bloco de código //
Variables:
startDust = 0;
Em seguida, no Object Editor, clique em Add e escolha Alarm > Alarm 0 para criar um novo Alarm Event. Será
neste Alarme que geraremos nossas nuvens de poeira.
Aqui, estamos criando variáveis temporárias para as posições x e y nas quais criar nosso Objeto de nuvem de
poeira cada vez que o Alarme dispara. Estamos nos certificando de que o jogador ainda esteja correndo e que esteja
realmente se movendo (verificando vx e vy). Se tudo isso der certo, criamos uma instância da nuvem de poeira.
Na parte inferior, você verá que redefinimos o Alarme de dentro do próprio Alarme. Estamos configurando para 8 etapas
(você pode alterar isso para ver o que acontece) e usar a variável carryLimit para desacelerar isso, assim como
carregar um item pesado desacelera o jogador.
Adicionando o código para criar instâncias da nuvem de poeira enquanto o player está em execução.
Feito isso, só precisamos fazer mais duas coisas para que a nuvem de poeira se comporte como esperado:
1. iniciar o processo de criação das nuvens de poeira quando o player começar a rodar; e
2. Interrompa o processo quando o player não estiver mais em execução.
Vamos cuidar do nº 1 primeiro: abra o Step Event do obj_player e encontre os blocos de código // Acelerar
se estiver executando e // Desacelerar se não estiver executando. Atualize esses dois blocos assim:
}
// Desacelerar se não estiver mais em
execução if (running == false) {
// Desaceleração
if (runSpeed > 0)
{ runSpeed -=
1; } startDust =
0; }
Você verá que estamos usando essa nova variável, startDust, como uma verificação para garantir que
começamos a acionar o alarme 0 do obj_player quando o jogador começar a correr.
Execute o jogo novamente e tente caminhar e correr. Quando você corre, nuvens de poeira devem
aparecer nos pés do jogador e girar suavemente e flutuar para longe.
Correndo pela nossa cidade com nuvens de poeira subindo aos pés do jogador.
É isso para esta sessão. No próximo, vamos usar outro recurso do GameMaker Studio 2, Sequências, para
criar animações divertidas que tocam quando o jogador dá esses itens para nossos três personagens.
8 Sessão 5
Nesta sessão, vamos mergulhar fundo nas Sequências para criar várias cenas animadas.
Em seguida, aprenderemos como verificar os itens que criamos e exibir a sequência correta,
entre muitas outras coisas.
No Asset Browser, clique com o botão direito do mouse no grupo Sprites e crie um novo grupo
chamado Sequences.
Usando o File Explorer (Windows) ou o Finder (Mac), navegue até a pasta Assets fornecida com
este curso e abra a pasta Sequences. Arraste todos os Sprites aqui para o novo subgrupo
Sequences no Asset Browser:
• spr_seq_bg_effect01
• spr_seq_bg_effect02
• spr_seq_bg_effect03
• spr_emote_exclamation_strip03
• spr_emote_flustered_strip05
• spr_emote_grumble_strip03
• spr_emote_shockLines_strip04
• spr_emote_sweatBubble_strip05
• spr_solidWhite
Abra cada um dos três Sprites bg_effect no Sprite Editor. Para cada um:
Abra cada um dos cinco spr_emote Sprites no Sprite Editor e faça o seguinte:
• Certifique-se de que cada Sprite Strip foi convertido corretamente em quadros; se não, siga o
etapas que usamos antes em Convertendo uma Sprite Strip manualmente para fazer isso
• Defina o valor de FPS para cada um em 10
Em seguida, abra spr_solidWhite e no Sprite Editor, defina sua Origin para Middle Center.
Depois de importar e limpar todos os recursos, clique com o botão direito do mouse em Sprites Group no
Asset Browser e escolha Create Group novamente. Nomeie esse novo subgrupo como "Sequências" e
arraste esses novos recursos para dentro.
Em seguida, precisamos importar várias novas animações do Baker para usar em nossa sequência. Isso
pode ficar pesado se não planejarmos agora, então: Se você ainda não o fez, organize seus recursos
Sprite no Navegador de recursos. Dentro do grupo Sprites, crie um grupo NPC, e um novo grupo para cada
um dos três personagens, assim:
Criando subgrupos para os ativos Sprite para cada um dos nossos três personagens.
Usando o File Explorer (Windows) ou o Finder (Mac), navegue até a pasta Ativos fornecida com este
curso e abra a pasta Caracteres e Itens. Arraste toda a lista de Sprites aqui para o novo subgrupo
Sprites > NPCs > Baker no Navegador de recursos:
• spr_baker_angry_strip04
• spr_baker_happy_strip04
• spr_baker_sad_strip04
• spr_baker_walk_down_strip04
• spr_baker_walk_left_strip04
• spr_baker_walk_right_strip04
• spr_baker_walk_up_strip04
Como acabamos de fazer com os Sprites emote, abra cada um desses novos Baker Sprites no Sprite
Editor e faça o
seguinte: • Certifique-se de que cada Sprite Strip foi convertido corretamente em quadros; se não, siga o
etapas que usamos antes em Convertendo uma Sprite Strip manualmente para fazer isso
• Defina o valor do FPS para 10
Editando os novos Baker Sprites para ter uma configuração correta de FPS e Origem. Observe como
removemos o sufixo _stripXX de cada Sprite e os colocamos no subgrupo Baker que criamos anteriormente
no Asset Browser.
Depois de lidar com todos esses novos recursos, é hora de criar nossa primeira sequência.
Clique com o botão direito do mouse no grupo Sequências do Navegador de ativos e escolha Criar > Sequência;
nomeie este novo ativo como seq_baker_happy.
Você se encontrará no Editor de Sequências. Os detalhes de todas as funções principais do Sequence Editor
podem ser encontrados no manual do GameMaker Studio 2, portanto, veremos o que precisamos enquanto
trabalhamos.
As sequências e o Editor de sequências podem parecer familiares se você já usou um programa de edição de vídeo antes. No
topo você tem a visualização Canvas, no canto inferior esquerdo você tem o Track Panel e no canto inferior direito você tem o Dope
Sheet (sua linha do tempo).
Uma Sequência é como uma animação de linha do tempo, mas podemos fazer outras coisas como chamar Scripts e enviar mensagens
para torná-los dinâmicos em nosso jogo. E, como muitas outras ferramentas semelhantes, as sequências usam quadros-chave
para permitir que você edite vários parâmetros dos ativos que você coloca neles.
Primeiro, olhe para a Caixa de Ferramentas da Tela (a barra de ferramentas horizontal no canto superior direito da exibição da Tela).
Clique na seta suspensa na ferramenta mais à direita para acessar as configurações da tela. Alterar a largura
para 1920 e a altura para 1080 (o mesmo que a câmera do nosso jogo, se você se lembra). Certifique-se de que Origin X e Y estejam
ambos definidos como 0.
Editando a largura e a altura de nossa tela de Sequência com a Caixa de Ferramentas de Tela.
Em seguida, vamos começar a projetar algo! Esta será a Sequência “feliz” para nosso NPC Baker
— será aquela que será reproduzida quando dermos a ele o item que ele mais deseja.
Uma nova trilha será criada com o nome do recurso e sua duração (relativa ao comprimento de sua
Sequência) será representada por uma nova chave de recurso na linha de tempo do Dope
Sheet (o bloco colorido).
Você também deve ver spr_solidWhite (um quadrado branco) na tela Sequence. Caso contrário,
certifique-se de mover o playhead amarelo na Dope Sheet para um ponto na linha do tempo onde o
sólido fica.
Arrastar nosso primeiro ativo (spr_solidWhite) cria uma nova trilha no Sequence Editor e uma nova chave
de ativo na Dope Sheet.
Se sua faixa spr_solidWhite parece estar em algum lugar no meio da linha do tempo, você pode clicar e arrastá-la
totalmente para a esquerda para colocá-la no início da Sequência. A borda esquerda (com o canto diagonal) deve se
alinhar com 0f (que é o primeiro quadro).
Antes de fazermos qualquer coisa, porém, aqui está uma observação importante: olhe acima do Track Panel para ver
uma série de ícones em forma de diamante. (Você pode passar o mouse sobre eles para ver o que eles fazem.)
O ícone mais à direita ( ) nos permite criar quadros-chave automaticamente apenas fazendo alterações nos
ativos na Tela. Isso é fantástico em muitas situações, mas para o que precisamos fazer agora, é melhor
desligarmos isso. Então, clique nele para garantir que não esteja destacado, assim:
Desativar a opção de criar quadros-chave automaticamente clicando no ícone mais à direita acima do Painel de
controle (conforme indicado pela seta aqui).
Com isso feito, clique no sólido branco atualmente flutuando em sua tela. Você verá nós familiares de
redimensionamento e rotação ao fazer isso. Usando-os, redimensione o sólido branco para cobrir toda a
Tela. (Tudo bem se ultrapassar os limites do Canvas.)
Em seguida, precisamos estender a chave do ativo para a trilha spr_solidWhite, para que o sólido
não desapareça após alguns quadros.
Passar o mouse sobre a borda direita da tecla de ativo revelará uma seta dupla; clique e arraste a
chave do ativo para esticá-la. (Definimos para 18 quadros, mas fique à vontade para brincar.)
Redimensionar a chave do ativo para que a duração do sólido branco seja maior.
Agora que nosso sólido dura mais do que alguns quadros e cobre todo o Canvas, precisamos
criar um efeito de fade. Para fazer isso, vamos fazer nossa transição sólida de transparente para
opaco.
No Painel da trilha, clique na seta à esquerda do nome da trilha (spr_solidWhite). Uma série de linhas
se abrirá; estes são chamados de faixas de parâmetros.
Como o nome sugere, para cada parâmetro de um recurso que você edita (como posição,
escala, opacidade/cor e mais), uma nova trilha de parâmetro é criada no Painel de trilhas.
Você pode ver que as duas faixas de parâmetros existentes, Posição e Escala, têm valores
que refletem as alterações que fizemos quando esticamos manualmente nosso sólido branco na Tela.
O que precisamos fazer é criar uma nova faixa de parâmetro para que possamos criar nosso efeito
de fade. Para fazer isso, clique no botão Add parameter track no Track Panel e escolha Color Multiply
no menu que aparece.
Clicando no botão “Add parameter track” para adicionar uma trilha Color Multiply.
Isso criará uma nova faixa de parâmetro para Color Multiply. Agora, não queremos apenas tornar o sólido branco
transparente o tempo todo; queremos que ele mude de transparente para opaco - e para isso, precisamos usar quadros-
chave.
Um quadro-chave é apenas isso; um momento no tempo em que algo acontece. Como ferramentas de edição
semelhantes, o Sequences Editor faz a transição automaticamente entre os parâmetros que você define nos quadros-chave —
que é como obtemos fades, rotações, dimensionamento e animação.
Então, vamos criar nosso primeiro quadro-chave. Certifique-se de mover o playhead amarelo para o início do Dope
Sheet, pois queremos que nosso sólido comece completamente transparente.
Em seguida, clique no losango azul oco à esquerda de Color Multiply para criar um novo quadro-chave, assim:
Em seguida, precisamos alterar o valor de Color Multiply naquele quadro-chave específico. Aqui é onde
você precisa ter cuidado: certifique-se de clicar no novo quadro-chave que você criou na linha do tempo,
para que fique destacado em azul.
Em seguida, clique na pequena amostra branca na faixa de parâmetros Color Multiply para abrir um seletor
de cores.
Defina o canal Alfa totalmente para 0 (alterando seu valor ou arrastando o controle deslizante triangular).
Quando terminar, clique em OK.
Alterar o canal Alpha na faixa de parâmetro Color Multiply para um quadro-chave específico.
Agora seu sólido branco desapareceu da tela (que é o que queríamos)! Para finalizar o efeito fade, precisamos
criar e editar outro quadro-chave.
Mova o playhead amarelo para o final da chave de ativo spr_solidWhite na Dope Sheet.
Clique no losango azul oco à esquerda de Color Multiply para criar um segundo quadro-chave.
Exatamente como acabamos de fazer, certifique-se de selecionar o novo quadro-chave e, em seguida, clique
na pequena amostra na faixa de parâmetros Color Multiply. Desta vez, mude o canal Alpha de volta para opaco
(255).
Feito isso, sinta-se à vontade para mover o indicador de reprodução amarelo para frente e para trás (também conhecido
como esfregar) para testar a transição. O sólido agora deve desaparecer de transparente para branco opaco.
Com esse fade inicial completo, vamos adicionar um plano de fundo à sequência e editá-lo também.
No Asset Browser, arraste spr_seq_bgEffect02 para o Track Panel no Sequences Editor. (Se esta nova trilha aparecer
abaixo da trilha spr_solidWhite, arraste-a para cima no Track Panel.)
Clique e arraste a chave de ativo para spr_seq_bgEffect02 para que comece um pouco antes do final do sólido branco,
assim:
Em seguida, adicionaremos o mesmo efeito de desvanecimento a esse ativo de fundo que fizemos com o sólido branco.
Usando as mesmas etapas que acabamos de seguir em Adicionar faixas de parâmetro e quadros-chave, adicione um efeito
de fade à faixa de fundo, da seguinte forma:
Observe a posição dos quadros-chave; isso dá à faixa spr_seq_bgEffect02 um fade in mais rápido.
Você pode precisar estender a chave de ativo para spr_solidWhite, ou então, conforme spr_seq_bgEffect02 aparece
gradualmente, não haverá nada abaixo dela, o que parecerá estranho.
Quando estiver pronto, pressione o botão Reproduzir para visualizar a Sequência. Você verá que nosso sólido
desaparece em branco e, em seguida, o plano de fundo animado desaparece rapidamente em cima disso.
Você notará que nossa Sequência é bem curta. Vamos torná-lo mais longo para que possamos continuar a adicionar a
ele.
No canto superior direito da Dope Sheet, você verá um número (60). Este é o número total de quadros em nossa
sequência. Altere esse número para 240 para obtermos uma sequência de quatro segundos.
Em seguida, clique e arraste o lado direito da chave de ativo spr_seq_bgEffect02 até o final da sequência. Como esse
recurso é um Sprite animado, ele continuará em loop até o final da linha do tempo.
Isso criará uma trilha para o Sprite; certifique-se de que esta faixa esteja acima das outras duas.
A posição do indicador de reprodução amarelo quando você arrastou o Sprite para o editor de sequência determina
onde na linha do tempo essa nova faixa começará. Mova a chave de ativo para o sprite Baker para que comece em
torno de onde o plano de fundo completa seu esmaecimento.
Posicionando o sprite Baker fora do Canvas e sua chave de ativo logo após o fundo desaparecer na
planilha Dope.
Certifique-se de que o indicador de reprodução esteja no início da chave de ativo de spr_baker_walk_left e que a chave
de ativo esteja selecionada.
Clique no botão Gravar uma nova chave ) na parte superior do Track Panel para criar um novo
( quadro-chave. Em seguida, clique no botão “Gravar alterações automaticamente” ( ) para acompanhar o que faremos a seguir.
Mova o cursor de reprodução para frente cerca de 15 quadros ou mais na Dope Sheet. Em seguida, no Canvas, clique e
arraste o Baker Sprite para a esquerda, para que ele apareça no centro da cena.
Ao registrar automaticamente nossas ações, podemos mover a reprodução para um ponto na linha do
tempo, mover nosso ativo Baker na tela e o Editor de sequências criará o quadro-chave e a faixa de
parâmetro corretos.
Se você clicar na seta à esquerda da trilha spr_baker_walk_left no Painel de trilhas, poderá ver todas as trilhas
de parâmetros desse ativo. Você notará que já existem dois quadros-chave para a faixa de parâmetro Position
porque movemos o sprite Baker.
Vamos fazer uma última coisa antes de prosseguir; dependendo de quanto tempo leva para o Baker Sprite
chegar ao centro da tela, pode parecer que ele está andando muito devagar ou muito rápido.
Portanto, para garantir que pareça correto, vamos usar uma combinação de duas técnicas.
Primeiro, certifique-se de clicar no botão “Gravar alterações automaticamente” na parte superior do painel Faixa para desativar
esse recurso. Vamos precisar fazer algum trabalho manual.
Em seguida, estenda a chave de ativo para o Padeiro ao longo da linha do tempo se seu movimento parecer muito abrupto.
Certifique-se de arrastar o segundo quadro-chave na faixa do parâmetro Position para aumentar a duração dessa
animação.
Estendendo a chave de ativo para o Baker Sprite e movendo seu quadro-chave de Posição para criar uma animação
mais longa.
Em seguida, clique no botão Add parameter track na trilha spr_baker_walk_left no Track Panel e escolha Image Speed.
A velocidade da imagem, se você se lembra, é uma variável interna para controlar a velocidade de animação dos Sprites. É
um multiplicador para a configuração de FPS no Sprite Editor. Por padrão, é definido como 100% (ou FPS x 1).
Ao alterar isso aqui, podemos ajustar manualmente a velocidade da animação de qualquer Sprite que colocarmos em uma
Sequência. Então, vamos ajustar um pouco a velocidade de animação do nosso Baker com isso.
Clique no losango azul oco à esquerda da trilha do parâmetro Image Speed para gravar um quadro-
chave para esse parâmetro.
Clique no quadro-chave na Dope Sheet para selecioná-lo e, em seguida, altere o valor da velocidade da
imagem para um número diferente (escolhemos 200%). Como você tem apenas um quadro-chave aqui, esse
valor persistirá pela duração da chave do recurso.
Reproduza a sequência e observe a mudança no tempo e na velocidade da animação. Se não parece certo
para você, vá em frente e ajuste ainda mais o valor da velocidade da imagem, ou ajuste a animação
dentro do Dope Sheet.
Quando estiver satisfeito com os resultados, certifique-se de salvar seu projeto e vamos para a próxima
etapa!
Em seguida, vamos mostrar as habilidades de dança do nosso Baker. Certifique-se de que o botão Gravar
alterações automaticamente esteja desativado. Em seguida, no Asset Browser, arraste o spr_baker_happy
Sprite na Tela.
Posicione o Sprite dançante para corresponder onde seu padeiro ambulante termina no meio da cena e certifique-
se de que a chave do ativo para a faixa spr_baker_happy comece onde o ambulante
A faixa Baker termina, assim:
Se você tocar a Sequência (ou esfregar o indicador de reprodução), verá que o Padeiro segue seu ritmo, para frente
e para trás. Agora, no entanto, ele está se movendo um pouco rápido demais.
Posicione o playhead onde a chave do recurso spr_baker_happy começa e clique no losango azul oco à esquerda
de Image Speed para criar um quadro-chave para este parâmetro.
Selecione o novo quadro-chave e altere o valor de Image Speed para 75%; isso deve lhe dar um resultado melhor.
Adicionando a faixa de parâmetro Image Speed para o Baker Sprite dançante e alterando seu valor com um
quadro-chave.
Em seguida, queremos adicionar um efeito divertido em que o padeiro dobra de tamanho cada vez que faz um loop
em sua animação de dança, para criar um drama divertido.
Mova o indicador de reprodução para o quadro na linha do tempo onde a chave do recurso Baker aparece pela
primeira vez. Grave um quadro-chave para as faixas Position e Scale, assim:
Em seguida, mova o indicador de reprodução cerca de 30 quadros para baixo na linha do tempo. Se sua chave de recurso
spr_baker_happy não for longa o suficiente, apenas estique-a.
Queremos fazer com que o Baker se encaixe repentinamente em 300% de seu tamanho. No entanto, por padrão, adicionar
quadros-chave para uma faixa de parâmetro (como Escala) e alterar seus valores causará automaticamente a interpolação entre os
quadros-chave.
Em outras palavras, se apenas adicionarmos um segundo quadro-chave e alterarmos a escala do padeiro para 300%, ele
aumentará gradualmente de 100% para o tamanho maior, o que não é o que queremos. Então, para facilitar nossa vida, vamos
desativar a interpolação.
Clique com o botão direito na trilha do parâmetro Scale para a trilha spr_baker_happy (no Painel da trilha) e escolha Interpolation >
Off, assim:
Selecione este novo quadro-chave e altere os valores de Escala no Painel de controle para 300%, 300%. Agora temos
um bom e grande Padeiro. Se você deslizar o indicador de reprodução para frente e para trás, verá que o Baker
não muda de tamanho gradualmente, mas se ajusta ao seu novo tamanho sempre que colocamos o novo quadro-chave.
Você notará que seu padeiro provavelmente está muito alto na tela. Vamos corrigir a posição do Padeiro
para mantê-lo enquadrado.
Como acabamos de fazer para a trilha do parâmetro Scale, clique com o botão direito na trilha do parâmetro
Position no Track Panel e escolha Interpolation > Off.
Com a reprodução no mesmo quadro que o novo quadro-chave Escala, clique no botão Gravar alterações
automaticamente novamente para ativá-lo.
Em seguida, clique e arraste o recurso Baker na tela para baixo para que ele fique mais centralizado na
tela. Você pode segurar a tecla Shift para restringir o movimento e tornar isso mais fácil ou usar o
Transform Gizmo (as setas vermelha e azul) para mover o recurso de maneiras específicas.
Um novo quadro-chave para a trilha Position será gravado automaticamente. Você pode clicar no botão
“Gravar alterações automaticamente” novamente para desativá-lo mais uma vez.
Usando o recurso “Registrar alterações automaticamente” para reposicionar o agora grande ativo Baker.
Repita os passos acima para “saltar” o tamanho do Baker mais duas vezes (de 300%, que você tem, para 450%
e depois de volta para 100%). A captura de tela a seguir mostra a configuração do quadro-chave que usamos
como referência:
Para terminar esta animação, vamos fazer mais duas coisas: fazer o Padeiro sair da Tela e, em seguida, criar
outro fade para nos ajudar na transição de volta para a jogabilidade da cidade.
Primeiro, certifique-se de que a chave do ativo para a trilha spr_baker_happy termine um ou dois quadros
após o par final de quadros-chave de Posição e Escala.
Em seguida, clique no recurso de chave spr_baker_walk_left no Dope Sheet e copie-o (CTRL-C no Windows,
CMD-C no Mac). Vamos fazer com que nosso Baker continue a andar depois que sua rotina de dança terminar.
Mova o indicador de reprodução amarelo para o quadro onde spr_baker_happy termina (você não deve ver o
padeiro dançante na tela neste quadro).
Cole (CTRL-V no Windows, CMD-V no Mac) e você deverá ver outra chave de recurso
spr_baker_walk_left a partir deste ponto no Dope Sheet, assim:
Ao fazer isso, podemos editar várias chaves de ativos para a mesma faixa - isso nos permite criar
Sequências que não ficam confusas com muitas faixas duplicadas.
Você notará que nosso padeiro ambulante está exatamente onde o deixamos antes de começar a dançar.
Se você clicar na seta à esquerda da trilha spr_baker_walk_left, verá que os quadros-chave para as
várias trilhas de parâmetro ainda estão no lugar.
Editando nosso Baker para que ele possa fazer sua saída.
Agora que nosso padeiro faz sua saída graciosa, precisamos desse efeito de fade final para completar a
sequência.
À medida que você se familiarizar com as ferramentas de Sequências, descobrirá que pode copiar, colar e
editar faixas, quadros-chave e muito mais para tornar seu trabalho mais rápido.
Vamos tentar isso agora duplicando primeiro uma faixa inteira. Clique na trilha spr_solidWhite original no Painel de
trilhas. Você pode pressionar CTRL-D no Windows (CMD-D no Mac) ou clicar no botão Duplicar Faixa ( ) na
parte inferior do Painel da Faixa para fazer uma cópia.
Arraste esta trilha duplicada para o topo do Track Panel. Mova sua chave de ativo ao longo da linha do
tempo para que ela comece logo antes do Baker sair da Tela. (Lembre-se, você precisa selecionar
a chave do ativo e seus quadros-chave para mover tudo junto.
Neste momento, nosso spr_solidWhite duplicado faz a mesma coisa que a faixa original; seu canal
Alpha transita de 0 a 255. Isso é o que queremos, mas também precisamos adicionar um efeito de fade-
out reverso.
No Dope Sheet, estenda o comprimento da chave do ativo spr_solidWhite para ter mais espaço para
trabalhar.
Em seguida, selecione o quadro-chave mais à direita na faixa de parâmetros Color Multiply. Pressione CTRL-C (CMD-C no Mac)
para copiar este quadro-chave.
Mova o indicador de reprodução alguns quadros para a direita e cole o quadro-chave que você copiou. Isso permitirá uma breve
pausa antes de esmaecermos o sólido branco novamente.
Em seguida, copie o primeiro quadro-chave na faixa de parâmetro Color Multiply para este segundo spr_solidWhite.
Mova a reprodução novamente um pouco mais para baixo na linha do tempo e cole o quadro-chave na nova posição na
faixa de parâmetro Color Multiply. Como esse quadro-chave copiado tem o canal Alpha definido como 0 (transparente), ele
criará um efeito de fade-out.
Uma última coisa: queremos que esse sólido branco apareça gradualmente para cobrir toda a Sequência. Em seguida,
queremos que ele desapareça para revelar a jogabilidade (cidade) novamente. Isso significa que quaisquer outras faixas na
sequência não podem ser visíveis quando o sólido branco desaparece gradualmente.
Certifique-se de que o recurso chave para a faixa spr_seq_bgEffect02 termine antes que o sólido branco desapareça, da
seguinte forma:
Copiar quadros-chave para facilitar a edição de faixas de parâmetros. Observe como o recurso de chave spr_seq_bgEffect02
termina no ponto na linha do tempo para que não esteja presente quando o segundo sólido branco desaparecer novamente.
Feito isso, sinta-se à vontade para visualizar sua Sequência novamente com o botão Reproduzir. Ajuste todos os principais
recursos ou quadros-chave para tornar suas transições mais curtas ou mais longas e ao seu gosto.
Quando importamos nossos recursos de som (de volta a Som e música), incluímos seis peças de música
especificamente para nossas Sequências. Esses são os arquivos que começam com snd_seq (como
snd_seq_bad01, snd_seq_good01 e assim por diante).
Escolha um dos arquivos snd_seq_good para usar em nossa Baker Sequence. (Você pode clicar duas vezes em
um som no Navegador de recursos para abri-lo no Editor de som e visualizá-lo.)
Arraste o ativo musical que você escolheu para o Painel de trilhas no Editor de sequências.
Você pode posicionar a chave de ativo para esta nova faixa como quiser; em nosso exemplo, colocamos logo no
início da Sequência.
As faixas de ativos de som têm faixas de parâmetros exclusivas para elas (Pitch e Volume).
Clique no botão Adicionar faixa de parâmetro e adicione uma faixa de parâmetro de volume à música.
Em seguida, crie um quadro-chave nesta nova faixa de parâmetro de volume próximo ou na posição em que o
padeiro caminha para a esquerda da cena.
Crie um segundo quadro-chave na faixa do parâmetro Volume no final da sequência, onde a segunda faixa
spr_solidWhite desapareceu.
Destaque este quadro-chave e altere o valor na faixa do parâmetro Volume para 0. Se você deslizar o indicador de
reprodução amarelo pela linha do tempo, verá que o volume do snd_seq_good01_BGM
faixa agora desaparece de 100 para 0.
Reduzindo gradualmente o volume da faixa de música usando quadros-chave na faixa de parâmetro de volume.
Se você escolheu iniciar sua faixa de música em um ponto diferente, ou deseja fazer fade in no início da Sequência (bem
como fazer fade out no final), você pode fazê-lo agora.
Basta repetir as etapas acima para adicionar mais dois quadros-chave à faixa de parâmetro da música e alterar o
Volume de 0 a 100.
Você pode visualizar sua Sequência pressionando o botão Reproduzir. Quando estiver satisfeito com a aparência e o
som da sua Sequência, é hora de seguir em frente.
Para completar a Sequência “feliz” do nosso Padeiro, precisamos adicionar algo novo: um par de Mensagens de
Transmissão.
As Mensagens de Transmissão são uma maneira das Sequências dentro do GameMaker Studio 2 se comunicarem com
o restante do jogo, fazendo exatamente o que o nome sugere: enviando uma mensagem.
Vamos adicionar nossa primeira mensagem de transmissão. Posicione o playhead amarelo no primeiro quadro da
Sequência.
Em seguida, clique no botão Add Broadcast Messages ( ) na parte superior da Dope Sheet. Digite esta mensagem
como sequenceStart.
Como tudo mais na Dope Sheet, esta Mensagem de Transmissão será enviada quando a Sequência for reproduzida
e atingir sua posição na linha do tempo. Se precisar ajustar a posição da mensagem de transmissão, basta clicar e
arrastá-la. Se precisar editá-lo, clique duas vezes nele.
Em seguida, mova o indicador de reprodução para o final de sua Sequência, um ou dois quadros após
a faixa superior spr_solidWhite desaparecer, mas antes do quadro final (em nosso caso, o quadro 240). Se você
precisar ajustar a chave do ativo spr_solidWhite para abrir espaço, faça isso.
Dica: Tudo bem se sua Sequência for um pouco além de onde a faixa
spr_solidWhite desaparece gradualmente. Você pode cortar a
Sequência se quiser, no entanto, alterando o número no canto superior
direito da Folha Dope (que definimos anteriormente como 240).
Por si só, essas Mensagens de Transmissão não “fazem” nada — mas, como veremos em breve, elas se tornarão
uma ferramenta poderosa para nos permitir controlar e monitorar nossas pequenas e divertidas animações.
Depois de terminar a sequência “feliz” do padeiro, é hora de fazer uma segunda. Usaremos para quando o jogador lhe
der um item sobre o qual ele não está muito entusiasmado.
No Navegador de ativos, clique com o botão direito do mouse em seq_baker_happy e escolha Duplicar. Renomeie
a Sequência duplicada seq_baker_sad.
Abra esta nova Sequência no Editor de Sequência. Precisamos substituir a animação que criamos aqui por uma
totalmente nova usando ativos diferentes. Mas como já definimos alguns parâmetros (como
o FPS, comprimento e adicionando as duas mensagens de transmissão), trabalhar com essa duplicata nos poupará algum tempo.
Mantenha as faixas spr_solidWhite que você usou para criar as transições fade in e fade out.
Clique em cada uma das outras faixas para os vários Baker Sprites e emotes que você usou para criar sua sequência “feliz” e
pressione Excluir (ou clique com o botão direito do mouse e escolha Excluir) para removê-los.
Desenhe uma nova Sequência para mostrar o Padeiro chateado, usando o seguinte do Recurso
Navegador:
Se você alterar o comprimento desta nova Sequência, lembre-se de mover a mensagem de transmissão final da sequência para
corresponder. Você pode clicar na mensagem de transmissão na parte superior da folha de informações e arrastá-la para a
esquerda e para a direita.
Não se esqueça de mudar a música aqui também; posicione qualquer recurso de som snd_seq_bad que você escolheu como
quiser e pressione o botão Reproduzir para visualizar sua Sequência.
Lembre-se de atenuar essa nova música “ruim” no final da Sequência (como acabamos de fazer em Adicionando música
à nossa Sequência).
Para remover a música “boa” original, clique na faixa do recurso Som e pressione a tecla Excluir (ou clique com o botão direito do
mouse e escolha Excluir).
Criando uma segunda sequência de Baker usando um fundo diferente, Baker Sprite e outros efeitos visuais.
Quando estiver satisfeito com esta segunda sequência, é hora de passar para os outros dois personagens.
Agora que o Padeiro tem suas duas Sequências dramáticas completas, precisamos fazer a mesma coisa para o
Professor.
Para ajudá-lo com isso, existem ativos específicos para professores. Usando o File Explorer
(Windows) ou o Finder (Mac), navegue até a pasta Ativos fornecida com este curso. Abra a pasta
Sprites > Characters and Items e arraste esses Sprites para o Asset Browser no GameMaker Studio 2:
• spr_teacher_angry_strip04
• spr_teacher_happy_strip03
• spr_teacher_sad_strip04
• spr_teacher_walk_down_strip04
• spr_teacher_walk_left_strip04
• spr_teacher_walk_right_strip04
• spr_teacher_walk_up_strip04
Como acabamos de fazer com os Baker Sprites, abra cada um deles no Sprite Editor e faça o seguinte: •
Verifique
se cada Sprite Strip foi convertido corretamente em quadros; se não, siga o
etapas que usamos antes em Convertendo uma Sprite Strip manualmente para fazer isso
• Defina o valor do FPS para 10
Depois de organizar os ativos do Professor, é hora de retornar ao Editor de Sequência. Usando tudo o que você
aprendeu nesta Sessão, crie mais duas Sequências para o Professor:
• seq_teacher_happy
• seq_teacher_sad
Novamente, o conteúdo, a animação, a duração, o tempo e a escolha da música dependem totalmente de você; tente
ser criativo e explore as possibilidades do Sequence Editor!
Com o Baker e o Teacher completos, podemos adicionar as duas Sequences para o Grocer
também.
Como antes, existem ativos para você usar aqui. Usando o File Explorer (Windows) ou o Finder (Mac),
navegue até a pasta Ativos fornecida com este curso. Abra a pasta Sprites > Characters and Items e
arraste esses Sprites para o Asset Browser no GameMaker Studio 2:
• spr_grocer_angry_strip04
• spr_grocer_happy_strip04
• spr_grocer_sad_strip04
• spr_grocer_walk_down_strip04
• spr_grocer_walk_left_strip04
• spr_grocer_walk_right_strip04
• spr_grocer_walk_up_strip04
E mais uma vez, abra cada um desses Sprites no Sprite Editor e faça o seguinte:
• Certifique-se de que cada Sprite Strip foi convertido corretamente em quadros; se não, siga o
etapas que usamos antes em Convertendo uma Sprite Strip manualmente para fazer isso
• Defina o valor do FPS para 10
Depois de organizar os ativos do Grocer, é hora de retornar ao Editor de Sequência. Usando tudo o
que você aprendeu nesta Sessão, crie mais duas Sequências para o Merceeiro:
• seq_grocer_happy
• seq_grocer_sad
Mais uma vez, o conteúdo, a animação, a duração, a escolha da música e o tempo dependem totalmente
de você; tente ser criativo e explore as possibilidades do Sequence Editor!
Importante: certifique-se de que suas duas Sequências do Grocer tenham o sequenceStart e sequenceEnd
Mensagens de transmissão!
No momento, as duas sequências que acabamos de criar não aparecem em nosso jogo, então precisamos
implementá-las.
• Restaure o controle para o player assim que uma Sequência terminar de tocar
Nossas Sequências são, na verdade, animações lineares. Para rastrear o que está acontecendo com eles e lidar com
algumas das funcionalidades listadas acima, vamos usar um Objeto para prestar atenção nas coisas e agir.
Felizmente, já temos um: obj_control. Portanto, clique duas vezes em obj_control no Navegador de recursos
para abri-lo. Em seguida, abra o evento de início do jogo.
No evento de início do jogo, adicione o seguinte código após o bloco de código // Item states:
// estados da sequência
enum seqState {
Não jogar,
esperando,
jogando,
finalizado,
}
// Variáveis de sequência
sequenceState = seqState.notPlaying;
curSeqLayer = ninguém;
curSeq = ninguém;
Você deve reconhecer esse primeiro lote; é outro enum, desta vez para rastrear o estado de nossas sequências.
Como só reproduziremos uma dessas animações de sequência por vez, podemos nos virar com esse conjunto simples.
Abaixo disso, você pode ver que estamos definindo sequenceState como seqState.notPlaying e inicializando mais duas
variáveis que usaremos em breve.
Em seguida, abra o Room Start Event de obj_control, que usamos antes para tocar música na cidade.
Adicione o seguinte bloco de código após o bloco de código // Play music based on Room:
Como você verá em breve, precisaremos prestar atenção em qual camada de Room nossas Sequences existem e onde elas
devem ser criadas (assim como fazemos quando criamos instâncias).
Há uma ruga, no entanto. Precisamos ter certeza de que essa camada (Cutscenes) existe em nossa sala da cidade. Então,
abra rm_gameMain no Asset Browser e veja o Room Editor.
Na parte inferior do painel Room Editor, você verá ícones para criar diferentes tipos de camadas.
Clique no botão Criar nova camada de ativo ( ) para criar uma nova camada de ativos.
Quando a nova camada aparecer no painel Camadas, clique com o botão direito do mouse e escolha Renomear para
nomeá-la Cutscenes. Arraste a nova camada para o topo da pilha.
Não colocaremos nada nesta camada, mas iremos direcioná-la ao exibir nossas Sequências.
Antes de continuarmos, vamos garantir que tudo o que configuramos até agora está funcionando e visualizar
nossa Sequência dentro do próprio jogo.
Abra obj_control novamente e no Object Editor, clique em Add Event. Escolha Pressionar tecla >
Letras > S.
; var _camY
= camera_get_view_y(view_camera[0])+floor(camera_get_view_height(view_camera[0])*0.5 );
Observe as variáveis _camX e _camY que configuramos aqui. Quando criamos nossa
sequência seq_baker_happy (e todas as outras), garantimos que a Origem X e a Origem Y
foram ambos 0. Mas isso realmente corresponde ao meio-centro da tela Sequence (e não ao canto superior
esquerdo, como você poderia esperar).
O cálculo _camX encontra a posição x da câmera do nosso jogo e adiciona metade da largura da câmera, que
seria o ponto médio horizontal de nossa visão da câmera, como vemos ao jogar o jogo.
O cálculo _camY faz a mesma coisa, mas para a altura. Mas, calculando ambos, obtemos o ponto central da
visão da câmera do nosso jogo e garantimos que nossa sequência se alinhe com ele quando for criada.
Criar uma Sequência aqui é como criar uma Instância; estamos direcionando uma camada, valores x e y e
escolhendo em qual Sequência aparecer.
A função final aqui (layer_depth()) é um pouco de limpeza. Só precisamos garantir que nossa camada de ativos Cutscenes esteja
sempre abaixo (mais perto da câmera) do que o resto da ação, para que nossas Sequências apareçam acima de tudo. (Fizemos a
mesma coisa para nosso objeto textbox.)
Mas lembre-se de que nosso obj_player, NPCs e itens de cidade usam esse código de classificação de profundidade
(profundidade =-y), o que significa que não podemos ter 100% de certeza de qual profundidade é a “mais próxima” o tempo todo.
Portanto, estamos definindo manualmente um valor muito baixo aqui apenas para jogar pelo seguro. (Armazenamos Cutscenes
neste curSeqLayer no Room Start Event de obj_control.)
Ok, com este evento de teste em vigor, salve seu projeto. Execute o jogo e pressione a tecla “S” do seu teclado assim que estiver
rodando. Você deve ver sua linda Sequência de Baker aparecer e tocar por cima de tudo!
Agora que sabemos que nossa Sequência funciona e já praticamos a criação de uma instância de uma Sequência, é hora de
começar a configurar a funcionalidade real do nosso jogo.
Sempre que, digamos, a sequência seq_baker_happy for reproduzida em nosso jogo, ela enviará
essas mensagens de transmissão à medida que a animação atingir os pontos apropriados em sua linha do
tempo. Então, no início, ele grita silenciosamente “sequenceStart” e, quando chega ao fim, grita “sequenceEnd”.
O que precisamos fazer é dizer ao obj_control para ouvir essas mensagens e fazer algo quando as ouvir.
Abra obj_control novamente no Editor de Objeto. Clique em Adicionar evento e escolha Outro >
Mensagem de transmissão.
}; quebrar;
}
Isso pode parecer complexo, mas é basicamente um código que usamos antes. Estamos usando
um acessador event_data especial para procurar mensagens de transmissão (que o GameMaker
Studio 2 entende como “mensagem”) e estamos fazendo isso em uma função de troca.
Existem dois casos nesta função de comutação; uma para cada uma das Mensagens de Transmissão que
incluímos em nossas Sequências Baker.
Incluímos duas mensagens de depuração aqui para que possamos testar se está funcionando. Execute o jogo
novamente e pressione a tecla “S” para iniciar a Sequência como antes.
Preste atenção na janela Output no GameMaker Studio 2. (Caso não a veja, você pode ir em Windows > Output
na barra de ferramentas para abri-la novamente). Você deve ver as mensagens de depuração que incluímos
aqui, mesmo que nada de novo esteja acontecendo visualmente em nosso jogo. (A Sequência será indicada por
um número de identificação e não por um nome.)
Revendo a janela de saída e encontrando as duas mensagens de depuração que confirmam que nossos novos eventos
obj_control estão funcionando.
Agora que obj_control está ouvindo corretamente o que nossa sequência está dizendo, podemos executar algum
controle.
Abra obj_control se ainda não estiver aberto e clique em Add Event. Escolha Etapa > Etapa.
// Sequências de controle
switch sequenceState {
case seqState.playing:
{ global.playerControl = false; };
quebrar;
caso seqState.concluído: {
// Remove Sequência
if (layer_sequence_exists(curSeqLayer,curSeq)) {
layer_sequence_destroy(curSeq); }
Esta é mais uma função de switch, com casos para os dois estados que estávamos configurando no
evento Broadcast Messages.
Para seqState.playing, estamos simplesmente removendo o controle do jogador, para que ele não possa se
mover ou fazer qualquer coisa enquanto a cena do Baker é reproduzida.
Pressione “S” no teclado para testar a sequência e, em seguida, sinta-se à vontade para apertar as setas do teclado
para mover o objeto do jogador. Você não deve ser capaz de se mover ou fazer qualquer outra coisa até que a
sequência seja reproduzida e destruída.
E com isso, realizamos tudo o que nos propusemos no início de Preparando para controlar uma Sequência.
Com o obj_control rastreando corretamente quando as sequências estão sendo reproduzidas, podemos
resolver outro problema que você pode ter notado. Atualmente, mesmo que uma Sequência seja reproduzida, ainda
podemos ouvir o outro áudio em nosso jogo (a música da cidade, seu ambiente e até a fonte).
Se uma Sequência estiver sendo reproduzida, queremos apenas ouvir o áudio dessa Sequência, mas, a menos
que especifiquemos o que fazer nessas situações, nosso jogo não saberá disso automaticamente.
// Variáveis do jogo
global.playerControl = verdadeiro;
global.gameOver = false;
global.gameStart = false;
cidadeBGMvolume = audio_sound_get_gain(snd_townBGM);
townAmbienceVolume = audio_sound_get_gain(snd_townAmbience);
Essas duas novas linhas vão nos ajudar a acompanhar os volumes iniciais (conhecidos no GameMaker
Studio 2 como ganho) tanto para a música quanto para o loop de som ambiente.
Como você pode ter ajustado o volume (ganho) desses ativos de som no Editor de som, primeiro queremos capturar o
que é esse ajuste. Usamos audio_sound_get_gain() para fazer isso.
Usando audio_sound_get_gain() para capturar o volume de um recurso de som, conforme definido no Editor de som.
Na instrução switch sequenceState sob o bloco de código // Control Sequences, atualize o caso seqState.playing
da seguinte forma:
// Sequências de controle
switch sequenceState {
case seqState.playing: { // Fade
out da música da cidade if
(audio_is_playing(snd_townBGM)) {
audio_sound_gain(snd_townBGM,0,60); }
Aqui estamos usando outra função, audio_sound_gain, para definir o volume de nossos dois ativos de som
para 0.
O terceiro argumento (60) nessas funções é o número de etapas que queremos usar para fazer essa alteração. Se o
número for 0, a mudança de volume acontecerá instantaneamente; se for mais alto, o GameMakerStudio 2
mudará gradualmente o volume do recurso Sound, criando um efeito de fade.
Você pode alterar esse número para fazer com que o som desapareça mais rapidamente ou mais lentamente.
// Sequências de controle
alterne o estado da sequência {
case seqState.playing: {
// Fade out da música da cidade
if (audio_is_playing(snd_townBGM)) {
audio_sound_gain(snd_townBGM,0,60);
}
// Fade out do ambiente da cidade
if (audio_is_playing(snd_townAmbience)) {
audio_sound_gain(snd_townAmbience,0,60);
}
global.playerControl = false;
}; quebrar;
caso seqState.concluído: {
// Remove Sequência
if (layer_sequence_exists(curSeqLayer,curSeq)) {
layer_sequence_destroy(curSeq);
}
// Restaura o controle para o jogador, reseta
global.playerControl = verdadeiro;
sequenceState = seqState.notPlaying;
curSeq = ninguém;
Aqui, estamos usando as novas variáveis que declaramos no evento de início do jogo de obj_control para restaurar
o volume (ganho) da música e dos ativos de som do ambiente depois que uma sequência é marcada como concluída.
Execute seu jogo novamente e teste-o, mas dando um item para um dos três NPCs. Você ouvirá o áudio da sequência com
clareza cristalina, e a música e o ambiente da cidade desaparecerão naturalmente. Quando você retornar ao jogo, o áudio
da cidade voltará a desaparecer.
8.26 Ajustando o áudio posicional 3D quando uma Sequência está sendo reproduzida
Você deve ter notado ao testar seu jogo que o áudio posicional 3D da fonte borbulhante da cidade ainda pode ser ouvido
enquanto uma Sequência está sendo reproduzida.
Usando uma técnica semelhante à que acabamos de fazer, vamos também garantir que quaisquer sons ambientais sejam
silenciados corretamente quando uma Sequência estiver sendo reproduzida.
// Variáveis do emissor
meuEmissor = 0;
volInit = 1;
Também no Create Event, atualize o bloco de código // Create emissor da seguinte forma:
// Cria emissor if
(useSound != noone) { if !
audio_is_playing(useSound) { myEmitter
= audio_emitter_create();
audio_emitter_position(meuEmissor,x,y,0);
audio_falloff_set_model(audio_falloff_exponent_distance);
audio_emitter_falloff(meuEmissor,fallStart,maxDistance,1); volInit =
audio_sound_get_gain(useSound);
audio_play_sound_on(myEmitter,useSound,1,1); }
Aqui, estamos definindo essa nova variável, volInit, novamente, mas obtendo o volume (ganho) de qualquer som
que um objeto ambiental tenha sido definido para reproduzir.
Abaixo do bloco de código // Depth sorting code, adicione um novo bloco de código:
}
}
}
Se você ler o código, verá que estamos usando os estados do obj_control para verificar se uma Sequência está
tocando ou foi finalizada e, em seguida, ajustando o volume (ganho) do nosso som ambiente de acordo.
O problema aqui, porém, é que, como o som 3D é sempre reproduzido por meio de um Emissor (como abordamos
em Adicionando um Emissor de Áudio), usamos audio_emitter_gain(). Isso não nos permite fazer a
transição do volume de um som ao longo do tempo, como audio_sound_gain() faz — porque um emissor já faz isso!
Em vez disso, audio_emitter_gain() define o volume máximo que um som 3D pode ter; se for 0, você nunca o
ouvirá, mesmo que o ouvinte (nosso objeto do jogador) esteja ao lado do objeto que possui aquele emissor.
Estamos fazendo isso no Step Event de obj_par_environment, e não em obj_control por um simples motivo: você
pode ter vários objetos ambientais com seu próprio áudio 3D, então faz sentido que cada um cuide de si mesmo.
Alterar o volume máximo de um som ambiente 3D dependendo se uma Sequência está sendo
reproduzida.
Execute o jogo novamente e teste nossa nova funcionalidade pressionando a tecla “S”. Desta vez, a música
da cidade, o ambiente e a fonte devem desaparecer, e você deve ouvir apenas o áudio da Sequência que toca.
Quando a Sequência terminar, todos os três sons devem voltar.
Isso vai bastar para esta sessão. Aprendemos como projetar Sequências, como
implementá-las em nosso jogo e como lidar com o controle de áudio. Como sempre, certifique-
se de salvar seu projeto!
9 Sessão 6
Em nossa sessão final, vamos colocar essas Sequências para valer. Aprenderemos a verificar qual item nosso
jogador está carregando ao se aproximar de cada personagem e jogar a Sequência correta.
Em seguida, rastrearemos se o jogador deu corretamente aos três NPCs os itens que eles desejam e, em caso
afirmativo, marcaremos que eles concluíram o jogo.
Vamos começar!
Agora que podemos criar uma Sequence, monitorá-la com Broadcast Messages e usar alguns estados habilitados
para enum para controlar algumas coisas, estamos prontos para ser um pouco mais ambiciosos.
Pode parecer muito, mas se seguirmos passo a passo, você verá que já construímos a maioria das ferramentas de
que precisamos!
Primeiro, vamos garantir que nossos NPCs digam coisas diferentes para o jogador, dependendo se o jogador
está carregando um item e se é o certo.
Para fazer isso, primeiro abra obj_par_npc e clique em Variable Definitions no Object Editor.
Precisamos adicionar várias novas definições de variáveis. Para cada um, clique no botão Adicionar e edite cada
coluna para corresponder ao que você vê aqui:
itemTextoFeito “Mensagem de agradecimento.” Corda Texto a ser exibido após o NPC ter
sido marcado como “concluído”
Lembre-se que se você tornar uma Definição de Variável um Ativo, o GameMaker Studio 2 permitirá que você escolha
qualquer Ativo por padrão. Se você quiser restringir esta escolha a um determinado tipo de Ativo (Objeto, Sequência,
etc.), você precisa clicar no ícone de engrenagem para essa Definição de Variável e especificar o tipo de Ativo.
Agora que temos essas predefinições, você pode personalizar o conteúdo de cada um dos três NPCs.
Clique no ícone Editar ao lado de cada uma das novas definições de variáveis que acabamos de adicionar e altere os
valores padrão. Você também pode revisar o que o Baker diz quando o jogador fala com ele pela primeira vez
(myText), para fornecer uma dica sobre o item que ele deseja.
Nome Padrão
meuTexto “Eu certamente gostaria de ter algo para me ajudar a assar essas tortas.”
sequênciafeliz seq_baker_happy
sequênciatriste seq_baker_sad
Adicionando valores personalizados para novas definições de variáveis NPC para o padeiro.
Quando estiver satisfeito com o Baker, abra obj_npc_teacher e faça a mesma coisa: edite cada uma das novas Variable
Definitions.
Certifique-se de escolher um objeto diferente para myItem. Aqui estão algumas recomendações:
Nome Padrão
meuTexto "Eu gostaria de ter algo para comer antes de dar esta aula."
sequênciafeliz seq_teacher_happy
sequênciatriste seq_teacher_sad
Assim que o Professor estiver completo, vamos passar para o Grocer. Abra obj_npc_grocer e edite suas
definições de variável.
Mais uma vez, escolha um objeto diferente para myItem. Aqui estão as nossas recomendações:
Nome Padrão
sequênciafeliz seq_grocer_happy
sequênciatriste seq_grocer_sad
Quando todos os três objetos NPC forem atualizados, estaremos prontos para seguir em frente.
Dica: Não faça nenhum dos três NPCs ter o mesmo item desejado.
Caso contrário, você não conseguirá terminar o jogo!
Se apenas jogarmos nosso jogo novamente agora, nada terá mudado. Isso ocorre porque precisamos adicionar a
capacidade de verificar qual item o jogador está carregando (se estiver carregando alguma coisa) e, em seguida,
exibir o texto correto.
Felizmente, pensamos no início de Pegando um item e adicionamos uma instrução if no Key Press - Space
Event do obj_player. Esta instrução if garantiu que uma caixa de texto apareceria se nos aproximássemos de um
NPC e pressionássemos a barra de espaço, mas apenas se não estivéssemos carregando um item.
Esse código estava dentro do // Se o jogador tiver bloco de código de controle, assim:
Isso nos dá a capacidade de adicionar outra instrução if — uma para quando o jogador estiver carregando um item.
Portanto, atualize o // Se próximo a um bloco de código NPC (que está dentro do // Se o jogador tiver bloco de
código de controle) da seguinte forma:
// Se perto de um NPC
if (próximo NPC) {
// Se o jogador não tiver um item if (hasItem ==
noone || hasItem == undefined) {
_texto = NPC próximo.meuTexto; if
(!instance_exists(obj_textbox)) {
iii = instance_create_depth(nearbyNPC.x,nearbyNPC.y-400,-
10000,obj_textbox);
iii.textToShow = _text; }
}
// Se o jogador tiver um item (e ele ainda existir) if (hasItem !
= noone && instance_exists(hasItem)) {
// Se o jogador tiver o item correto if
(hasItem.object_index == nas proximidadesNPC.myItem) { _text
= nas proximidadesNPC.itemTextHappy; }
iii = instance_create_depth(nearbyNPC.x,nearbyNPC.y-400,-
10000,obj_textbox);
iii.textToShow = _text;
}
}
}
Salve seu projeto e execute seu jogo. Você deve ser capaz de fazer três coisas:
1. Fale com qualquer um dos três NPCs sem carregar um Objeto; eles devem dizer o que você colocar
na Definição de Variável myText
2. Fale com um NPC enquanto carrega o objeto que você definiu para ele na Variável myItem
Definição; eles devem dizer o que você definir como definição de variável itemTextHappy
3. Fale com um NPC enquanto carrega qualquer objeto que não seja o objeto myItem; eles devem
dizer o que você definir como definição de variável itemTextSad
Pressionar a barra de espaço ao lado do Baker agora deve nos dar um texto diferente se não estivermos carregando um
item, se estivermos carregando o item correto e se estivermos carregando um item incorreto.
Nossos NPCs agora podem dizer se estamos carregando um item e qual. Agora é hora de garantir que o jogo
execute a Sequência correta, dependendo do item.
Atualmente podemos tocar a Sequência “feliz” do nosso Baker (seq_baker_happy) pressionando a tecla “S”. No
entanto, o que queremos que aconteça é o seguinte:
Então, como queremos reproduzir nossas sequências depois de abrir uma caixa de texto, vamos usar a própria
caixa de texto para fazer o trabalho pesado.
Primeiro, abra obj_textbox. Em seu Create Event, adicione esta linha à lista de variáveis no bloco de código //
Textbox variables:
sequênciaToShow = ninguém;
Em seguida, abra o evento Alarm 0 de obj_textbox e encontre o bloco de código // Destroy me que escrevemos
antes:
// Destrua-me
global.playerControl = 1;
instância_destroy();
}
}
// Destrua-me
instance_destroy();
Você notará que estamos realizando uma verificação para ver se a nova variável que acabamos
de adicionar (sequenceToShow) é algo diferente de seu valor padrão. Se não for, continuamos como de costume.
Porém, se sequenceToShow tiver um valor diferente, estamos fazendo algo com o qual já deveríamos estar
familiarizados: é exatamente o mesmo código que escrevemos em Testing our Sequence. Só que agora, em vez
de pressionar uma tecla para lançar uma Sequência, estamos fazendo isso através do objeto de caixa de texto.
Por fim, no final deste bloco de código está a mesma função instance_destroy() de antes, para que possamos
nos livrar da caixa de texto quando não precisarmos mais dela.
Atualizando o Alarme 0 de obj_textbox para agora criar a Sequência apropriada antes que ela se destrua.
Agora que obj_textbox pode começar a reproduzir uma sequência, precisamos acionar esse comportamento
real e informar à caixa de texto qual sequência reproduzir. Para fazer isso, precisamos voltar ao nosso Objeto
do jogador.
Abra obj_player mais uma vez e abra seu Key Press - Space Event.
var _texto;
E altere para:
(Tudo o que estamos fazendo aqui é inicializar outra variável (_seq) sem nenhum valor na mesma linha de antes.)
Em seguida, precisamos atualizar o // Se próximo a um bloco de código NPC novamente para nos permitir dizer a uma
caixa de texto qual sequência reproduzir quando terminar. Edite este bloco de código assim:
// Se perto de um NPC
if (próximo NPC) {
// Se o jogador não tiver um item if (hasItem
== noone || hasItem == undefined) {
_texto = NPC próximo.meuTexto;
if (!instance_exists(obj_textbox)) {
iii = instance_create_depth(nearbyNPC.x,nearbyNPC.y-400,-
10000,obj_textbox);
iii.textToShow = _text; }
}
// Se o jogador tiver um item (e ele ainda existir) if
(hasItem != noone && instance_exists(hasItem)) {
// Se o jogador tiver o item correto if
(hasItem.object_index == nas proximidadesNPC.myItem)
{ _text = nas proximidadesNPC.itemTextHappy;
_seq = NPC próximo.sequenceHappy; }
}
}
Como você pode ver, estamos simplesmente adicionando a nova variável temporária _seq e atribuindo a ela um valor que
depende do item que o jogador está carregando. Então, se o jogador estiver carregando um item, passamos o valor de
_seq para obj_textbox por meio da nova variável sequenceToShow que acabamos de criar.
A maneira mais fácil de entender isso é vê-lo em ação. Então, mais uma vez, salve seu projeto e execute seu jogo. Você
deve ser capaz de fazer as três coisas a seguir:
1. Fale com qualquer um dos três NPCs sem carregar um Objeto; eles devem dizer tudo o que você
colocar na definição de variável myText, como antes
2. Fale com o mesmo NPC enquanto carrega o objeto que você definiu para eles no myItem
Definição de Variável; eles devem dizer o que você definir como definição de variável itemTextHappy e,
em seguida, a sequência "feliz" deles deve ser reproduzida
3. Fale com o mesmo NPC novamente enquanto carrega qualquer objeto que não seja o objeto myItem;
eles devem dizer o que você definir como definição de variável itemTextSad e, em seguida, a
sequência "triste" deles deve ser reproduzida
Em todos os três casos, o jogador deve ser capaz de continuar se movendo (ou carregando um item)
após interagir com o NPC.
Você deve ter notado algo estranho ao testar nossas sequências agora. Dependendo de qual personagem
você dá um item, você pode notar que a música para sua Sequência soou baixa, ou distante, ou fora de uma
direção particular.
Bem, como se vê, uma Sequência também é um Emissor - assim como nossa fonte borbulhante. Portanto,
dependendo de onde o jogador está na sala quando a Sequência é reproduzida, você pode ouvir o áudio
da Sequência de forma diferente.
Quando usamos a tecla “S” para testar nossa Sequência (voltando a Testando nossa Sequência), a Sequência
estava sempre alinhada com o Objeto do jogador, o que significava que seu Emissor estava bem em cima do
Ouvinte do jogador — então tudo parecia correto.
Mas agora com nossos NPCs esse não é o caso, então precisamos fazer uma pequena adição ao
obj_player para corrigir isso.
No bloco de código // If Moving, localize a linha // Move audio listener with me, que deve ficar assim:
Precisamos atualizar isso para verificar as sequências e, se houver uma, ajustar o ouvinte do jogador para
que ele se alinhe com a sequência.
var _camX =
camera_get_view_x(view_camera[0])+andar(camera_get_view_width(view_camera[0])*0.5)
;
var _camY =
camera_get_view_y(view_camera[0])+andar(camera_get_view_height(view_camera[0])*0,5
);
audio_listener_set_position(0,_camX,_camY,0);
}
outro {
// Caso contrário, mova o ouvinte de áudio comigo
audio_listener_set_position(0,x,y,0);
}
}
Neste código atualizado, estamos verificando a variável sequenceState de obj_control, para ver se ela foi definida
como a constante enum seqState.playing (o que significa que uma sequência está sendo reproduzida no
momento).
Se isso for verdade, usamos o mesmo código de verificação de câmera que usamos antes no evento de alarme
0 de obj_textbox e o usamos para definir temporariamente a posição do ouvinte do objeto do jogador.
Se uma Sequência não estiver tocando, mantemos esse Ouvinte alinhado com o jogador, como fizemos antes.
Execute o jogo novamente e dê um item para um dos NPCs. Agora você deve ouvir que o áudio da
Sequência está corretamente “centralizado” e não soa como se estivesse sendo reproduzido fora da tela em
algum lugar.
Em seguida, precisamos tornar nosso loop de jogo de fornecimento de itens um pouco mais realista. Quando você
traz o item correto para um NPC, esse item deve desaparecer e o jogador não deve mais carregá-lo, já que você
devolveu o item ao NPC.
(Isso não acontecerá com outros itens, já que o NPC não os quer e você pode precisar entregá-los a outra pessoa.)
Como sabemos qual é o item correto para cada personagem? Bem, atualmente, cada NPC tem uma Definição de
Variável definida no Editor de Objetos. Por exemplo, definimos a variável myItem do padeiro como obj_item01 em
Alterando o que os NPCs dizem.
Mas agora também precisamos criar outra variável para nos ajudar a rastrear o status de um NPC, para que
possamos alterá-lo quando eles receberem o item correto. E como temos um objeto pai para todos os NPCs
(obj_par_npc), isso pode ser feito facilmente.
Assim como fizemos para nosso jogador e nossos itens, vamos criar um enum para nossos NPCs.
Abra obj_control e seu evento de início de jogo. Abaixo do bloco de código // Sequence variables, adicione
este novo bloco de código:
// estados do NPC
enum npcState {
normal,
feito,
}
Na parte inferior da janela Variable Definitions, clique em Add e crie duas novas variáveis com as seguintes
propriedades:
Usaremos esta variável (myState) para marcar quando o NPC para o qual você deu um item recebeu o item correto.
Depois que um NPC tiver o item que deseja, você não poderá mais tentar dar itens a ele, pois eles estão "prontos".
E, como você verá, usaremos a nova variável doneSprite para informar visualmente ao jogador que o NPC recebeu o
item desejado.
Para manter as coisas simples, vamos usar um Alarme no Objeto do jogador para mudar o estado dos NPCs
próximos para “concluído” e remover o item correto da posse do jogador.
Abra obj_player no navegador de recursos. No Editor de objetos, clique em Adicionar evento e escolha Alarmes >
Alarme 1.
// Remove Objeto
Você verá que não há nada de novo aqui, em termos de código. No bloco de código // Remove Object,
estamos dizendo ao objeto que o jogador está segurando (hasItem) para se destruir. No bloco de código //
Mark NPC as done, estamos usando a nova enumeração npcState para definir essa nova variável
(myState) no NPC próximo.
Adicionando o novo Alarme 1 ao obj_player para lidar com itens e marcar os NPCs como "concluídos".
Agora que temos esse Alarme, precisamos acioná-lo no momento certo. Abra o Key Press do obj_player
- Evento Espacial.
Encontre o // Se o jogador tiver o bloco de código de item correto (que está aninhado no // Se o jogador tiver o bloco de
código de controle) e atualize-o da seguinte forma:
Como já codificamos uma instrução if aqui para verificar se nosso jogador está carregando o objeto correto, podemos usar
esse local para acionar o alarme 1.
Agora podemos usar esse novo enum npcState para controlar um pouco mais nossos NPCs. Para fazer isso, precisamos adicionar
algum código que mudará a aparência de nossos NPCs, dependendo do estado deles.
} }; quebrar;
case npcState.done: {
if (doneSprite != noone && sprite_index != doneSprite) { sprite_index =
doneSprite; } }; quebrar;
Adicionamos uma instrução switch aqui; o caso npcState.normal se comporta exatamente como antes.
No caso npcState.done, no entanto, estamos simplesmente alterando o sprite do NPC para o valor de doneSprite.
Agora que nossos NPCs podem mudar seu próprio Sprite quando forem marcados como “concluídos”,
precisamos especificar o que esse Sprite será para cada um deles.
Clique no botão Edit para a definição da variável doneSprite e escolha spr_baker_happy Sprite.
Em seguida, abra obj_npc_teacher e faça a mesma coisa: clique em Variable Definitions, edite
a linha doneSprite e escolha spr_teacher_happy.
Por fim, abra obj_npc_grocer e repita o processo. Escolha spr_grocer_happy como seu valor
doneSprite.
Com tudo isso feito, salve seu projeto e execute seu jogo novamente para testá-lo. Tente isto:
Há mais um passo para completar nosso ciclo de jogo principal. Quando o jogador fala com um NPC
depois que o NPC já possui o item desejado, o NPC deve dizer algo diferente — aquela string
itemTextDone que adicionamos como uma Definição de Variável a obj_par_npc.
Felizmente, já configuramos tudo o que precisamos para fazer isso: criamos um texto para esta
situação para cada um de nossos NPCs e agora marcamos um NPC como “pronto” quando o Objeto
do jogador dá a ele o item correto.
Tudo o que resta é verificar se um NPC está “pronto” antes de abrir a caixa de texto usual.
Para fazer isso, abra o obj_player mais uma vez e seu Key Press – Space Event.
Precisamos fazer uma alteração adicional no grande // Se próximo a um bloco de código NPC, atualize-o
assim:
// Se estiver perto de
um NPC if
(nearbyNPC) { // Se o NPC ainda
estiver disponível if (nearbyNPC.myState ==
npcState.normal) { // Se o jogador não tiver
um item if (hasItem == noone) {
_texto = NPC próximo.meuTexto;
if (!instance_exists(obj_textbox)) {
iii = instance_create_depth(nearbyNPC.x,nearbyNPC.y-400,-
10000,obj_textbox);
iii.textToShow = _text; }
}
// Se o jogador tiver um item (e ele ainda existir) if
(hasItem != noone && instance_exists(hasItem)) {
// Se o jogador tiver o item correto if
(hasItem.object_index == nas proximidadesNPC.myItem)
{ _text = nas proximidadesNPC.itemTextHappy;
_seq = NPC próximo.sequenceHappy; //
Verifica se devemos remover o item, marque NPC
alarm[1] = 10; }
if (!instance_exists(obj_textbox)) {
iii = instance_create_depth(nearbyNPC.x,nearbyNPC.y-400,-
10000,obj_textbox);
iii.textToShow = _text;
iii.sequenceToShow = _seq;
}
}
}
// Se o NPC estiver "pronto"
if (nearbyNPC.myState == npcState.done) {
_text = nearNPC.itemTextDone;
if (!instance_exists(obj_textbox)) {
iii = instance_create_depth(nearbyNPC.x,nearbyNPC.y-400,-
10000,obj_textbox);
iii.textToShow = _text;
}
}
}
O que fizemos aqui foi adicionar outra instrução if para verificar se o NPC próximo teve sua variável myState definida como
npcState.done ou não. Se não, fazemos tudo o que fazíamos antes. Nesse caso, no entanto, o NPC agora dirá apenas o
texto armazenado em sua definição de variável itemTextDone.
Uma última limpeza antes de continuarmos: de volta ao Testing our Sequence , adicionamos um Key Press – S Event ao
obj_control para que pudéssemos testar nossa Sequence.
Clique com o botão direito do mouse em Key Press – S Event e escolha Delete Event. Agora o jogador não poderá acionar
acidentalmente nosso teste.
Nosso ciclo de jogo principal agora está intacto. Mas o que realmente precisamos é de um final para o nosso jogo. Como
podemos marcar nossos NPCs como “prontos”, temos uma maneira de acompanhar o progresso do jogador.
O que queremos fazer agora é verificar se todos os três NPCs estão “prontos” e, em seguida, jogar uma
sequência especial de “game over” antes de reiniciar o jogo.
Usando o File Explorer (Windows) ou o Finder (Mac), navegue até a pasta Ativos fornecida com este curso. Vá
para Sprites > User Interface e arraste os seguintes arquivos para o Asset Browser.
• spr_title_youDidIt
• spr_title_thankYou
No GameMaker Studio 2, abra ambos os novos Sprites e defina sua Origem como Centro Central.
Organize os Ativos no Navegador de Ativos se você estiver fazendo isso.
Definindo a origem de um dos novos Sprites do título. Observe como os organizamos no Asset
Browser.
Em seguida, clique com o botão direito do mouse no grupo Sequências no Navegador de ativos e escolha
Criar > Sequência. Nomeie esta nova Sequência seq_gameOver.
Abra seq_gameOver; no Sequence Editor, clique no botão Canvas frame settings na barra de ferramentas Canvas
(no canto superior direito).
Agora que o Canvas está pronto, desenhe uma Sequência usando os seguintes elementos:
Se você precisar de uma atualização sobre o uso de faixas de parâmetro ou mensagens de transmissão, consulte Iniciando
nossa primeira sequência.
Em nosso exemplo de sequência Game Over, com ativos de título, fades e uma faixa de música
Quando estiver satisfeito com o design da sua Sequência, vamos começar a fazê-la funcionar!
Para começar o final do nosso jogo, primeiro precisamos rastrear se o jogador atingiu seu objetivo (dar os
itens corretos aos três NPCs).
Como já temos uma maneira de denotar isso (definimos o estado de cada NPC como
npcState.done), podemos usar algumas instruções if simples para verificar!
Abra obj_control e seu evento de início de jogo. Adicione a seguinte linha ao bloco de código //
Game variables:
// Variáveis do jogo
global.playerControl = verdadeiro;
cidadeBGMvolume = audio_sound_get_gain(snd_townBGM);
townAmbienceVolume = audio_sound_get_gain(snd_townAmbience);
global.gameOver = false;
Usaremos essa nova variável global para controlar quando terminamos o jogo.
Em seguida, abra o Step Event de obj_control. Edite o bloco de código // Control Sequences da seguinte forma:
// Sequências de controle
switch sequenceState {
case seqState.playing: { // Fade
out da música da cidade if
(audio_is_playing(snd_townBGM)) {
audio_sound_gain(snd_townBGM,0,60); }
// Restaura a música da
cidade if (audio_is_playing(snd_townBGM) && audio_sound_get_gain(snd_townBGM) <
townBGMvolume)
{ audio_sound_gain(snd_townBGM,townBGMvolume,60); }
// Restaura o ambiente da
cidade if (audio_is_playing(snd_townAmbience) &&
audio_sound_get_gain(snd_townAmbience) < townAmbienceVolume) {
audio_sound_gain(snd_townAmbience,townAmbienceVolume,60); }
}
}
}
}; quebrar;
}
Este novo bloco de código // Verificar se os NPCs estão “concluídos” será colocado na fila no final do nosso jogo. Isso
pode parecer um pouco pesado, mas há apenas duas declarações if aqui:
• Um para garantir que nossos três objetos NPC estejam lá (só para garantir)
• Outro para perguntar, em uma linha, se cada um deles foi definido como "concluído"
Se ambas as declarações forem satisfeitas, removemos o controle do player, definimos um Alarme e definimos
global.gameOver como verdadeiro.
Neste Step Event, definimos o alarme 0, mas ainda não o adicionamos. Vamos fazer isso agora.
Neste novo Evento de Alarme, queremos criar uma instância da Sequência “game over”. Agora, podemos apenas
copiar e colar o código que usamos em obj_textbox em Reproduzindo uma sequência por meio do objeto Textbox.
No entanto, como mencionamos em Criando nossas próprias funções dentro de Script Assets, se
vamos reutilizar os mesmos bits de código repetidamente, é melhor transformar esse código em uma função.
Então, antes de continuarmos, vamos cuidar disso.
Copie ou corte este código que está dentro do bloco de código // Create Sequence if apropriado:
Em seguida, clique com o botão direito do mouse no grupo Scripts no Navegador de recursos e escolha Criar > Script.
Nomeie este novo recurso de script como scr_sequenceControl.
function scr_playSequence(){
function scr_playSequence(){
// Definir sequência para o centro da visualização da
câmera var _camX =
camera_get_view_x(view_camera[0])+andar(camera_get_view_width(view_camera[0])*0.5)
;
var _camY =
camera_get_view_y(view_camera[0])+floor(camera_get_view_height(view_camera[0])*0.5 );
}
}
Em seguida, edite a função para incluir um argumento chamado _seqToPlay. Em seguida, substitua qualquer instância
de sequenceToShow por _seqToPlay, assim:
function scr_playSequence(_seqToPlay){
// Definir sequência para o centro da visualização da
câmera var _camX =
camera_get_view_x(view_camera[0])+andar(camera_get_view_width(view_camera[0])*0.5)
;
var _camY =
camera_get_view_y(view_camera[0])+floor(camera_get_view_height(view_camera[0])*0.5 );
}
}
Substitua todo o bloco de código // Create Sequence if apropriado por esta versão mais simples:
if (sequenceToShow != ninguém) {
// Reproduzir Sequência de NPC
scr_playSequence(sequenceToShow);
}
No que diz respeito ao seu jogo, nada mudou. Acabamos de pegar aquele grande bloco de código deste evento e
transformá-lo em uma função reutilizável.
Nosso obj_textbox Alarm 0 atualizado. É mais simples porque usa a nova função scr_playSequence, mas faz a mesma coisa
de antes.
Agora que transformamos a capacidade de reproduzir uma sequência em uma função simples e reutilizável,
podemos adicionar essa funcionalidade a obj_control.
Abra obj_control novamente. Configuramos a capacidade do obj_control para saber quando é hora de acionar a
sequência “game over”, mas agora temos que fazer isso.
Abra o Evento de Alarme 0 que fizemos em Configurando a Sequência "Game Over". Estará em branco; adicione
o seguinte bloco de código:
Aqui, estamos usando a nova função e dizendo a ela para reproduzir a sequência seq_gameOver que acabamos
de projetar.
Usando a nova função scr_playSequence para jogar a sequência “game over” de obj_control.
Feito isso, rode seu jogo e teste-o. Traga a cada um dos três NPCs seus itens desejados; depois de entregar
o terceiro item correto, sua Sequência de “game over” deve começar automaticamente.
Você vai notar uma coisa, porém: uma vez que sua Sequência termina, nada mais acontece.
O que precisamos fazer é incluir a peça final do quebra-cabeça: uma maneira de seu jogo
reiniciar automaticamente.
Até agora, usamos Mensagens de Transmissão de nossas Sequências para dizer a outros Objetos no jogo para fazer certas coisas.
Mas podemos dar um passo adiante e realmente executar o código de dentro de uma própria Sequence!
Então, vamos criar uma nova função que terminará nosso jogo para nós e a chamaremos de dentro de nossa sequência
seq_gameOver.
Primeiro, clique com o botão direito do mouse no grupo Scripts no Navegador de recursos e escolha Criar > Script. Chame esse novo
recurso de script de scr_gameControl.
function scr_gameOver(){
final_jogo();
}
Como você deve ter adivinhado, esta função simples e integrada sai imediatamente do jogo e fecha sua janela.
Abra seq_gameOver novamente e mova o playhead amarelo para um ponto logo após o fim da animação, mas antes do quadro
final da sequência. (Se você precisar ajustar algumas chaves de ativos para ter espaço, vá em frente.)
No topo da Dope Sheet, clique no botão Add Moment (aparece. ); uma pequena janela “Momento” aparecerá
No campo desta janela, digite scr_gameOver — o nome completo da sua função provavelmente será preenchido automaticamente
enquanto você digita.
Depois de digitar (ou selecionar), clique em OK. Você verá que uma pequena marca amarela foi adicionada à linha do tempo:
Adicionando um momento à nossa sequência de “game over”. A função scr_gameOver() será chamada neste
momento.
Este é um momento; um ponto na linha do tempo em que podemos chamar uma função de dentro de
uma sequência.
Agora, quando nossa sequência “game over” for reproduzida, ela chamará a função scr_gameOver() que acabamos
de escrever, que encerrará nosso jogo imediatamente.
Execute seu jogo novamente e teste; dê o item correto para cada um dos três NPCs. Depois de dar ao
terceiro NPC seu item correto e sua Sequência “feliz” ser reproduzida, o seq_gameOver
A sequência será reproduzida automaticamente e agora fará com que o jogo termine.
Com o loop principal do jogo completo, precisaremos de uma introdução adequada ao nosso jogo — e
isso significa uma tela de título!
Usando o File Explorer (Windows) ou o Finder (Mac), navegue até a pasta Ativos fornecida com este curso.
Vá para Sprites > User Interface e arraste os arquivos para o Asset Browser:
• spr_bg_mainTitle
• spr_title_mainLogo
• spr_title_pressEnter
(Como sempre, recomendamos mantê-los organizados no Asset Browser — por exemplo, em um grupo Sprites >
User Interface.)
Abra spr_title_mainLogo e spr_title_pressEnter Sprites. Defina a Origem de ambos como Centro Central.
Em seguida, precisamos criar uma nova sala para usar como tela de título.
No Navegador de recursos, clique com o botão direito do mouse no grupo Salas e escolha Criar > Sala. Nomeie
esta nova sala rm_mainTitle.
Abra rm_mainTitle se ainda não estiver aberto; usando o painel Room Editor, altere as seguintes propriedades:
Editando nossa nova tela de título Room. As propriedades que precisamos alterar estão todas visíveis à esquerda.
Em seguida, na seção Propriedades da camada de fundo, há um menu suspenso que atualmente diz "Sem Sprite".
Clique aqui e escolha o Spr_bg_mainTitle Sprite que acabamos de importar. Você notará que é uma imagem
quadrada, posicionada no canto superior esquerdo da sala.
O que queremos fazer é ladrilhar a imagem. Então, na seção Background Layer Properties, faça o seguinte:
Devemos testar nosso novo Room para ver o que fizemos até agora em ação. No entanto, se executarmos o
jogo novamente agora, não o veremos.
Isso é por causa da ordem atual do nosso jogo. Você pode perguntar: se nosso jogo tem várias Salas,
como o GameMaker Studio 2 sabe qual carregar primeiro?
Procure no Navegador de ativos; você verá uma seção especial chamada Acesso rápido. Abra-o e você verá
outra subseção chamada Room Order.
A ordem da sala permite que você saiba qual sala em seu jogo será carregada primeiro.
Nesta lista de Ordem das Salas, você verá todas as Salas do seu jogo. (No momento só temos dois.)
Você notará que rm_gameMain tem um pequeno ícone inicial próximo a ele; isso indica que rm_gameMain
será a primeira Sala mostrada ao jogador quando nosso jogo for carregado.
Para alterar isso, arraste rm_titleScreen acima de rm_gameMain. Se rm_titleScreen tiver o ícone inicial ao
lado, você sabe que será a “primeira” Sala do jogo.
Configurando rm_titleScreen para ser a primeira Sala que o jogador vê. Observe que, se você clicar no ícone inicial ao lado
de uma sala, poderá acessar o Gerenciador de salas.
Feito isso, execute o jogo novamente para testá-lo. Você deve ver nossa nova sala da tela de título e a
imagem de fundo lado a lado rolando na diagonal.
Agora que temos nossa tela de título Room configurada, precisamos preenchê-la com duas coisas: um logotipo e um prompt
para o jogador começar a jogar.
Abra rm_titleScreen novamente. Na seção Layers do Room Editor, crie uma nova Asset Layer.
Com essa nova camada selecionada, arraste o Spr_title_mainLogo Sprite do Asset Browser para a Room. Posicione-o como quiser.
Em seguida, vamos criar um prompt animado para incentivar os jogadores a pressionar uma tecla para iniciar o jogo. E
felizmente, temos a ferramenta perfeita para fazer isso: Sequências!
Clique com o botão direito do mouse no grupo Sequências no Navegador de ativos e escolha Criar > Sequência.
Renomeie esta nova Sequência seq_mainTitle.
Esta Sequence não precisa ter um Canvas grande como os anteriores, então vamos fazer algumas configurações.
(Falando tecnicamente, não precisamos realmente redimensionar a tela, mas estamos fazendo isso apenas para manter as
coisas organizadas.)
Em seguida, arraste o Spr_title_pressEnter Sprite do Asset Browser para a Tela (posicione-o no centro).
Na Dope Sheet, certifique-se de que a chave do ativo para a trilha spr_title_pressEnter abrange toda a Sequência.
Mova o indicador de reprodução amarelo um pouco para dentro da sequência (digamos, em torno do quadro 5 ou mais).
Selecione a chave do ativo e clique no botão "Adicionar trilha de parâmetro" no Painel de trilha. Escolha adicionar uma faixa de
parâmetro Color Multiply.
Selecione o novo quadro-chave e clique na amostra de cor na faixa de parâmetro Color Multiply (se você não vir esse detalhe,
clique na seta à esquerda de spr_title_pressEnter no Painel de controle para revelá-lo).
No seletor de cores que aparece, defina o canal alfa para 0. Clique em “OK” quando terminar.
Tornamos o recurso "Pressione Enter para reproduzir" transparente.
Em seguida, mova o indicador de reprodução para perto do final da linha do tempo, mas não para o último quadro. Sugerimos
em torno do quadro 30.
Se você percorrer a Sequência ou pressionar o botão Reproduzir para reproduzi-la, deverá ver o recurso de texto passar de
transparente para opaco.
Agora que temos um efeito de fade linear simples, podemos fazer algo novo com ele.
O que realmente queremos é que esse recurso apareça e desapareça repetidamente, enquanto o jogador permanecer na tela
de título do nosso jogo.
Para fazer isso, clique no botão Alterar modo de reprodução ( ) várias vezes para alternar entre as três
opções de reprodução: reproduzir uma vez, repetir e “pingue-pongue”.
Clique no botão Reproduzir para visualizar sua Sequência novamente e você verá que agora ela avança até
atingir o final da linha do tempo, ponto em que ela é reproduzida para trás e depois repetida.
Selecione a Logo Asset Layer que criamos anteriormente. Arraste seq_mainTitle do Asset Browser para a
Room, na camada Logo.
Quando estiver satisfeito com o layout da tela de título, execute o jogo para testá-lo. Você deve ver o prompt
“Press Enter to Play” aparecendo e desaparecendo, enquanto o plano de fundo lado a lado rola indefinidamente.
Nossa nova tela de título está linda, mas ainda precisamos adicionar funcionalidades a ela.
Atualmente, no entanto, obj_control existe apenas em rm_gameMain (nós o colocamos lá em Using control
Objects). Precisamos mudar isso.
Na seção Instances Layer Properties, você encontrará uma longa lista de todas as instâncias que foram
colocadas nessa camada. Se você percorrer a lista, encontrará a instância de obj_control que
colocamos antes.
Colocando obj_control em rm_mainTitle. (Aqui, estamos colocando-o “fora” da Sala, mas não importa
onde esteja.)
No Editor de Objetos, existem opções como Visível, Sólido, etc. Uma dessas opções é Persistente.
Normalmente, um Objeto só existe dentro da Sala em que foi criado (ou colocado). Se você mudar
de Sala, qualquer Objeto da Sala anterior deixa de existir, no que diz respeito ao seu jogo.
No entanto, um objeto persistente permanece no jogo depois de criado (ou quando o jogo carrega uma
sala que o contém). Um Objeto persistente viaja entre as Salas automaticamente.
Em seguida, vamos fazer com que o obj_control verifique se o jogador pressiona a tecla “Enter” enquanto
está na tela de título — se o fizer, seguirá para o jogo principal.
Abra o Game Start Event de obj_control e atualize o bloco de código // Game variables da seguinte forma:
// Variáveis do jogo
global.playerControl = true;
cidadeBGMvolume = audio_sound_get_gain(snd_townBGM);
townAmbienceVolume = audio_sound_get_gain(snd_townAmbience);
global.gameOver = false;
global.gameStart = false;
Em seguida, clique em Add Event no Object Editor e escolha Key Pressed > Enter.
Neste novo Key Press – Enter Event, adicione o seguinte bloco de código:
global.gameStart = verdadeiro;
room_goto(rm_gameMain);
}
}
Neste evento, estamos verificando se estamos na tela de título e, se estiver, interrompemos todo o áudio que possa estar sendo
reproduzido e, em seguida, vamos diretamente para a sala de jogo principal.
Uma última coisa: vamos adicionar um pouco de música a esta tela de título!
Já tocamos música antes, dependendo da sala em que estamos, então vamos expandir essa funcionalidade.
Atualize a instrução switch no bloco de código // Play music based on Room da seguinte forma:
Isso reproduzirá uma das faixas de música Sequence como um tema de título enquanto você estiver na tela de título.
(Sinta-se à vontade para escolher um recurso de som diferente, se preferir.)
Execute o jogo novamente para testá-lo novamente. Na tela de título, você deve ouvir sua música em loop e o recurso
“Press Enter to Play” piscará suavemente para dentro e para fora.
Pressione a tecla Enter - você deve fazer a transição imediatamente para a sala de jogo, onde poderá começar o jogo como
antes.
E com esta adição, você de fato completou sua pequena cidade! Como sempre, certifique-se de salvar seu projeto.
Com a conclusão dessas seis sessões, você aprendeu muito sobre o GameMaker Studio 2. Desde a criação de Salas,
até a criação de Objetos de jogador, controle de animação e até mesmo o design de Sequências.
Mas com cada ferramenta de design, sempre há muito mais para aprender e novas maneiras de criar. Na Sessão Bônus
incluída neste curso, você encontrará alguns truques e sugestões adicionais para continuar melhorando sua pequena
cidade.
10 Sessão Bônus
Nesta sessão, você encontrará algumas dicas opcionais para melhorar sua cidade, bem como alguns desafios que
o ajudarão a aprender mais.
Usando o File Explorer (Windows) ou o Finder (Mac), navegue até a pasta Ativos fornecida com este curso. Vá para
Sprites > Characters and Items e arraste esses dois arquivos para o Asset Browser:
• spr_shadow_npc
• spr_shadow_player
Definindo a origem para ambos os sprites de sombra e organizando cada um no navegador de recursos.
Em seguida, abra obj_player. No Editor de objeto, clique em Adicionar evento e escolha Desenhar > Desenhar.
De volta a Desenhando as coisas manualmente, usamos um evento Draw para fazer nosso objeto de caixa de texto
desenhar o sprite da caixa de texto e o texto que se encaixa nele.
Faremos a mesma coisa aqui para o nosso jogador; ele atrairá tanto os Sprites do jogador (como já está fazendo agora)
quanto o novo Sprite das sombras.
// Desenha a sombra
draw_sprite_ext(spr_shadow_player,0,x,y,1,1,0,c_white,0.3);
draw_set_alpha(1);
// Desenha o jogador
desenhe_self();
Observe que na função draw_sprite_ext(), estamos definindo a posição do Sprite da sombra para ser a mesma do jogador
(para que fique alinhado com os pés do jogador). Também estamos definindo o último argumento nesta função como 0,3
para tornar o sprite translúcido.
E como fizemos antes com o objeto de caixa de texto, estamos usando draw_self() para não precisarmos nos preocupar
com nenhum código de desenho complexo. O Objeto do jogador continuará a desenhar corretamente suas várias
animações.
Quando estiver pronto, execute o jogo e confira aquela nova sombra chique!
Usando o que você acabou de aprender, você pode usar aquele novo Spr_shadow_npc Sprite para adicionar uma
sombra aos NPCs? Lembre-se, você pode editar obj_par_npc para fazer uma alteração que afete todos os
três caracteres automaticamente.
Atualmente, os itens do jogo saltam para os braços do jogador e caem sem cerimônia quando você os
pega e os coloca no chão. Mas com um pouco de código extra, podemos animar esses itens no
tempo com as próprias animações do jogador.
Adicione estas duas linhas ao bloco de código // Set my state (a lista de variáveis que criamos):
putDownSp = 17;
pickUpSp = 17;
Em seguida, abra o Step Event (ou End Step Event, se você o alterou) e edite os casos
itemState.taken e itemState.puttingBack dentro do // Depth, bloco de código de animação, assim:
// Profundidade,
alternância de
animação myState { // Se o item estiver no
chão caso itemState.idle:
{ profundidade
=-y; };
quebrar; // Se o item foi obtido
case itemState.taken: { //
Mantém o item alinhado com o jogador var
_result = scr_itemPosition(); x =
_resultado[0];
profundidade =
_resultado[2]; if (instance_exists(obj_player))
{ // Anima o item sendo pego if
(obj_player.myState == playerState.pickingUp) { // Espera
até o terceiro quadro da animação if
(obj_player.image_index >= 2) { if (y >
_result[1]) { y -=
pickUpSp; }
}
}
// Posiciona o item enquanto está sendo
carregado else { y =
_result[1]; }
} }; quebrar;
caso itemState.puttingBack: {
// Animar item sendo colocado if
(instance_exists(obj_player) && obj_player.myState ==
playerState.puttingDown) { if (y
< putDownY) { y +=
putDownSp; }
} }; quebrar;
}
Essas novas variáveis que declaramos no evento de criação de obj_par_item são apenas para velocidade (e você
pode modificá-las se as coisas não parecerem corretas para você).
No caso de troca em // Se o item foi levado, estamos simplesmente verificando se o objeto do jogador
está em seu estado “pegando”. Nesse caso, ajustamos a posição y do item até atingir o y
valor retornado por nossa função scr_itemPosition(). (Volte a Retornar resultados de funções.)
Se o jogador terminou seu estado de "pegar", mantemos a posição y do item sob controle, como fizemos
antes.
Abaixo disso, no próximo caso, substituímos o código anteriormente simples por um novo // item do
Animate sendo colocado no bloco de código.
Neste bloco de código, também estamos verificando o estado do objeto do jogador e, se estiver
"colocando no chão", ajustamos a posição y do item no chão. (Definimos putDownY em Key Press –
Space Event de obj_player, em Colocando o item de volta no chão.)
Com essa atualização feita, rode seu jogo novamente. Tente pegar e colocar itens e observe como eles
se animam suavemente!
Os Sprites para o prompt e a caixa de texto são bem simples; você pode projetar novos e implementá-los?
Se precisar de um lembrete, consulte Configurando nossa caixa de texto. E não se esqueça, esses Sprites podem ser
animados!
Atualmente, nossa Little Town tem seis itens. Você notará que os itens podem parecer relevantes para mais de um
personagem (por exemplo: quem apreciaria mais uma maçã? O Professor ou o Merceeiro?).
Isso torna divertido escrever um texto de dica (como fizemos em Mudando o que os NPCs dizem) e nos dá uma maneira
de fazer nosso jogador pensar.
Que outros itens você poderia adicionar ao jogo para desafiar o jogador?
Você pode alterar o que cada um dos três NPCs diz para sua definição de variável myText para dar dicas mais
claras ou mais difíceis sobre qual item eles desejam. Você também pode esconder os seis itens em locais mais
tortuosos ou projetar sua cidade para torná-los mais difíceis de detectar. De que outra forma você pode
desafiar seus jogadores?
Não superamos a exportação do seu jogo para dar a outros devido a algumas diferenças dependendo das
plataformas. No entanto, para obter detalhes sobre isso:
Como sempre, salve seu projeto e faça o que fizer — continue criando jogos incríveis do GameMaker Studio
2!