[TUTORIAL] Como organizar seu projeto

Ver o tópico anterior Ver o tópico seguinte Ir em baixo

[TUTORIAL] Como organizar seu projeto

Mensagem por Mr.Rafael em Sab 07 Set 2013, 11:20

TUTORIAL: ORGANIZANDO SEU PROJETO:
(algumas dicas rápidas de como não se perder na hora de criar os seus jogos)

E aí, galerinha, beleza? Bom, hoje eu estou aqui sem intenções de ensinar, mas sim para dar uns toques sobre como vocês constroem os seus projetos e como organizam o conteúdo...

Por exemplo: sabe quando você usa centenas de Sprites e Objetos, todos com o nome "sprite0", "sprite1", "object10"? E sabe aqueles momentos em que você quer alterar a velocidade do jogador, mas para isso terá que mudar diretamente em todos os eventos de tecla? Mais além: e quando você não curte muito Scripts?

Pois bem... eu vou dar umas dicas rápidas sobre como você pode dar uma boa organizada nos seus projetos. Sim: apenas dicas rápidas, pois eu perderia um dia inteiro explicando 100% sobre as "boas condutas" (que algumas nem eu mesmo sigo). yes

PARTE #1: NOMEANDO RECURSOS:

Vamos montar um projeto de mentirinha para ilustrar. Ele possui alguns inimigos, espinhos, pontos espalhados e claro, o jogador. Começamos pelos Sprites e encontramos isto:


Mas que porcaria é essa? Meu jogo é feito usando apenas quadrados, mas não consigo identificar quem é quem nessa história! Quem é o jogador? E quem são os inimigos?

Então, vamos nomear os Sprites e ver como fica:


Ah, agora sim! Bem melhor. Outra dica: para localizá-los com facilidade, coloque "_spr" ou "_obj". sorrindo

PARTE #2: ORGANIZANDO RECURSOS:

Agora que eu possuo todos os Sprites nomeados, posso criar os Objetos agora. Geralmente, quando você está inspirado, já cria a quantidade certa que vai utilizar. E então ficamos com isto:


"Mas qual é o problema, Rafas?", perguntarão. Oras, veja só como esses elementos estão: todos bagunçados! E se eu querer colocar mais inimigos e recursos depois? Vou ter que ficar lá catando milho?

Senhoras e senhores: apresentamos as sub-pastas:


Veja só como tudo está mais limpo. Agora, se eu quero colocar o jogador na tela, eu não preciso mais ficar procurando às cegas por ele. Digo o mesmo para inimigos específicos.

PARTE #3: DEFININDO VARIÁVEIS GLOBAIS:

Não estou aqui para explicar o que são variáveis globais nem quando e como você deve utilizá-las. Nosso foco é apenas organizar o projeto (por mais "gambiarrístico" que pareça). Então... vamos lá. Smile

Quem me deu essa dica foi o nosso bom e velho amigo Ninja_PHP (volte, por favor ;-;). Você já encontrou casos em que você definia variáveis globais dentro do Creation Code da primeira Room? Tipo isso aqui:


Ah, como eu ODIAVA quando eu usava milhares de variáveis globais e o GM acusava que algumas delas não existiam, mesmo quando estava tudo ali...

Mas e aí? Como vamos resolver esse problema? Simples: Crie uma Room vazia para iniciar o jogo e coloque um Objeto que cria todas as variáveis logo no começo. Tipo isso aqui:


Como não existe nenhum objeto na tela que precise das variáveis, o GM não acusará erros durante a inicialização do jogo. E logo após as variáveis terem sido criadas, ele partirá para a verdadeira primeira tela do jogo.

Adicionalmente, você pode colocar na Room este código:

Código:
global.level = (string("Level ") + string(global.level_counter));
PARTE #4: EVITANDO TRABALHOS DOBRADOS:

Essa é interessante e creio que todo mundo que já tenha um certo grau de experiência com programação já conheça. Vamos lá: Sabe quando você usa os eventos do GM para criar suas ações e vai definindo o movimento do personagem? Pois é... imagine que você colocou isso aqui:


Tranquilo, não é? Apesar do nível já montado estar favorecendo a um jogo de plataforma, vamos brincar um pouco e dar uma jogabilidade Maze ao jogador. Ou seja: ele se movimenta para cima, para baixo, para esquerda ou para direita.

Mas eu não quero mais a velocidade 5. Eu achei muito ruim e agora eu quero mudar para 6, e aí? Pois é, Champz, vai ter que mudar o valor nos 4 eventos! E se você ainda não gostou da velocidade, não tem problema: é só ficar lá trocando até achar.

Vamos evitar essa estupidez utilizando uma simples variável. Que tal?


Agora só precisamos definir a variável player_spd no Create do personagem e está tudo feito. Mas espere: eu tenho mais ideias! Por que não colocamos uma variável que mede a saúde dele mesmo? E por que não uma seleção de armas? E que tal um diálogo para ele?

E lá vamos nós! cheers


Meldels, que porcaria é essa? Por que RAIOS eu estou definindo uma variável de saúde para o jogador sendo que já existia a global.player_health? O que significa aquela coisa chamada vacajairo? E olha só: "eu sou o cavalero das treva"!

Não banque o engraçadinho na hora de programar o seu jogo: coloque nomes de variáveis que ajudem você a saber o que cada uma faz. E se você quiser escapulir um pouquinho, pelo menos comente. Organizando melhor essa atrocidade, deixamos assim:


Notou como tudo ficou mais limpo? Pois é, antigamente eu não ligava muito para isso, mas hoje eu transformo as mecânicas dos meus jogos em simples trocas de valores. Smile

PARTE #5: EVITANDO DUPLICATAS DE OBJETOS:

É completamente normal utilizar a mesma mecânica de um inimigo no outro. Podemos fazer isso quando, por exemplo, queremos que os inimigos Y andem da mesma forma que os inimigos X. Agora, saca só isso:


Parece que está tudo bem, certo? Mas vamos supor que a mecânica do primeiro inimigo (que duplicamos mais 3 vezes) não está funcionando como deveria... e aí, o que fazemos agora? Deletamos todos os inimigos criados, corrigimos a mecânica do primeiro inimigo e duplicamos de novo? Hum... é, seria interessante, mas quando já tínhamos mais de 15 fases que usavam aqueles objetos, comofas? Vamos ter que perder ainda mais tempo recolocando os objetos novos no lugar? E se durante essa trabalheira toda eu perceber que os inimigos se movimentam de uma forma muito lenta e eu quisesse mudar a velocidade só um pouquinho?

PELAMORDEDEUS, NÃO FAÇA ISSO! Imagine o trabalho que você vai ter no futuro apenas para fazer um simples ajuste. assustado
quando a mecânica de um inimigo tiver que ser igual a de um pré-existente, use Parents. Observe:


Com um objeto vazio e apenas clicando em uma seleção de objetos, duplicamos inteiramente a mecânica do primeiro inimigo. Viu como é mais fácil? Mas espere, podemos ir mais além!

Se você quiser organizar ainda mais, pode criar um objeto "fantasma" apenas com essa finalidade. Com isso, você não só livra os inimigos como também diminui a quantidade de eventos de colisão mais adiante. Vejamos:


Nesse caso, ao invés de checarmos colisões com o enemy_obj, enemy2_obj, enemy3_obj e enemy4_obj, agora podemos reduzir tudo isso checando a colisão apenas com o enemy_typedef. Very Happy

PARTE #6: ORGANIZANDO SEU CÓDIGO:

Essa é a melhor parte e acho que vai acordar muito programador de GML por aí (incluindo os mais experientes). Se bem que, olhando melhor, acho que isso fica como lição para qualquer linguagem que você for utilizar.

Ao pressionar a barra de espaço, o jogador atira um projétil, que vai depender da arma que ele estiver utilizando. As armas podem ser representadas pelos 4 elementos da natureza, que são o ar, o fogo, a terra e a água.

Vamos dar uma olhada no código:


Mas que porcaria de código é esse? Fui eu mesmo que escrevi isso?
Bom: para economizar imagens (pois estou com preguiça de tirar prints contínuos e superlotar o tópico com esse tipo de coisa), eu utilizarei a tag "CODE".

Primeiro de tudo: organize a indentação desses ifs:

Código:
if player_weapon=0
       {
       instance_create(self.x,self.y,bullet_air_obj)
       }
else if player_weapon=1
       {
       instance_create(self.x,self.y,bullet_fire_obj)
       }
else if player_weapon=2
       {
       instance_create(self.x,self.y,bullet_earth_obj)
       }
else if player_weapon=3
       {
       instance_create(self.x,self.y,bullet_water_obj)
       }
Acho que vou dar uma espaçada nesses elses também...
Segundo: coloque as condições em parênteses:

Código:
if (player_weapon=0)
       {
       instance_create(self.x,self.y,bullet_air_obj)
       }

else if (player_weapon=1)
       {
       instance_create(self.x,self.y,bullet_fire_obj)
       }

else if (player_weapon=2)
       {
       instance_create(self.x,self.y,bullet_earth_obj)
       }

else if (player_weapon=3)
       {
       instance_create(self.x,self.y,bullet_water_obj)
       }
Terceiro: remova esse "=" (igualar) e utilize "==" (comparar). Dê também uma espaçada nesses sinais:

Código:
if (player_weapon == 0)
       {
       instance_create(self.x,self.y,bullet_air_obj)
       }

else if (player_weapon == 1)
       {
       instance_create(self.x,self.y,bullet_fire_obj)
       }

else if (player_weapon == 2)
       {
       instance_create(self.x,self.y,bullet_earth_obj)
       }

else if (player_weapon == 3)
       {
       instance_create(self.x,self.y,bullet_water_obj)
       }
E para finalizar: coloque o ";" (ponto e vírgula) no fim de cada comando:

Código:
if (player_weapon == 0)
       {
       instance_create(self.x,self.y,bullet_air_obj);
       }

else if (player_weapon == 1)
       {
       instance_create(self.x,self.y,bullet_fire_obj);
       }

else if (player_weapon == 2)
       {
       instance_create(self.x,self.y,bullet_earth_obj);
       }

else if (player_weapon == 3)
       {
       instance_create(self.x,self.y,bullet_water_obj);
       }
"Ah, Rafas, mas o ponto e vírgula não é obrigatório no GML.", dirão alguns. Pode até não ser, mas o ponto e vírgula sempre indicará o final de cada comando, facilitando a leitura e deixando o seu código consideravelmente mais legível quando em uma linha só. Por exemplo: se você entrar no Chatbox e quiser mostrar esse código, ficará mais fácil na hora de "separar" os comandos, consequentemente facilitando a sua ajuda. Também vale lembrar que uma boa quantidade de linguagens de programação exigem o uso do ponto e vírgula. Então se você pretende estudar algo como C/C++, é bom começar a ter boas práticas. Smile

Tudo resolvido com este código, certo? ERRADO! Por que RAIOS você vai usar um emaranhado de ifs e elses quando se pode usar o switch? --\'
Deixei isso de propósito, quis ir mostrando primeiro como você organiza. Só que agora eu vou mostrar como otimizar este código:

Código:
switch (player_weapon)
       {
       case 0:
            {
            instance_create(self.x,self.y,bullet_air_obj);
            break;
            }
      
       case 1:
            {
            instance_create(self.x,self.y,bullet_fire_obj);
            break;
            }
      
      case 2:
            {
            instance_create(self.x,self.y,bullet_earth_obj);
            break;
            }
      
      case 3:
            {
            instance_create(self.x,self.y,bullet_water_obj);
            break;
            }
       }
Mas ainda falta uma coisinha bem pequena, mas que pode fazer toda a diferença depois: comentários. Mesmo que pareça um tanto quanto óbvio saber a arma que o jogador está utilizando olhando o nome dos objetos, você sempre pode ter a chance de se deparar com nomes como "bullet1_obj", "bullet2_obj", "bullet3_obj" e "bullet4_obj". Vamos lá:

Código:
// Checagem de armas
switch (player_weapon)
       {
       // Arma de ar
       case 0:
            {
            instance_create(self.x,self.y,bullet_air_obj);
            break;
            }
      
      // Arma de fogo
       case 1:
            {
            instance_create(self.x,self.y,bullet_fire_obj);
            break;
            }
      
      // Arma de terra
       case 2:
            {
            instance_create(self.x,self.y,bullet_earth_obj);
            break;
            }
      
      // Arma de água
       case 3:
            {
            instance_create(self.x,self.y,bullet_water_obj);
            break;
            }
       }
Comentar não dói nada. Ame as "//" (duas barras para a direita) e deixe o seu código mais fácil de entender. Smile
A propósito: sempre que você tiver códigos muito extensos mas ainda vai querer adicionar mais coisas em um determinado evento, recomendo que crie um Script com o código e no evento desejado basta usar o comando script_execute(nome_do_seu_script).

PALAVRAS FINAIS: FIM DO TUTORIAL:

Bom, é só isso! Não foi um tutorial tão extenso e a maioria das coisas já ficou bem na cara por causa das imagens.
Obrigado por ler e espero ter ajudado em alguma coisa. Very Happy

o/

Mr.Rafael

Ranking : Nota A
Número de Mensagens : 383
Data de inscrição : 05/10/2010
Notas recebidas : A-C-B-A
Reputação : 57
Insignia 1 x 0 Insignia 2 x 0 Insignia 3 x 0
Prêmios
   : 0
   : 1
   : 2

Voltar ao Topo Ir em baixo

Re: [TUTORIAL] Como organizar seu projeto

Mensagem por fredcobain em Sab 07 Set 2013, 12:14

Um dos melhores tutoriais já compartilhados aqui na GMBR.
Ah se todos seguissem esses conselhos... o mundo seria muito melhor.
=)

Não obstante, seu tutorial está aprovado e coroado como um dos "Escolha da Staff".

Parabéns e obrigado por contribuir com essa obra prima.

fredcobain

Ranking : Sem avaliações
Número de Mensagens : 691
Idade : 35
Data de inscrição : 14/04/2011
Reputação : 162
Insignia 1 x 0 Insignia 2 x 0 Insignia 3 x 0
Prêmios
   : 0
   : 0
   : 0

Voltar ao Topo Ir em baixo

Ver o tópico anterior Ver o tópico seguinte Voltar ao Topo

- Tópicos similares

 
Permissão deste fórum:
Você não pode responder aos tópicos neste fórum