Termos básicos de programação e como eles funcionam no GMPrograma: conjunto de declarações (statements) que instruem o computador a determinado funcionamento.
- Code:
{
declaração;
declaração;
...
}
São escritos nos objetos (dentro dos eventos>Execute code), nas rooms (settings>Creatuon code) e em scripts. Cada programa é delimitado por chaves, mas se ele sozinho for o conteúdo de um bloco de código, então não precisa colocar chaves. Cada declaração deve terminar em ponto-e-vírgula para evitar problemas. Game Maker diferencia letras minúsculas de maiúsculas, portanto cuidado.
Variável: um espaço na memória reservado para receber dados - números reais ou textos. Eles são identificados por nomes. Para criar uma variável, basta digitar um nome começado por letra ou underline e atribuir um valor qualquer.
- Code:
a=100; //Variável a é igual ao número 100.
zz=5.5; //Variável com valor numérico 5.5 (com ponto, não vírgula).
nome="Vic Viper"; //Variável nome com valor em texto (string - entre aspas) Vic Viper.
Algumas variáveis já são pré-definidas como:
x - coordenada horizontal na tela
y - coordenada vertical na tela
id - identificador individual de instância de objetos.
Variáveis individuais funcionam dentro de um objeto e valem apenas internamente, não afetando outros objetos. O valor atribuído fica na variável até ser trocado e desaparece da memória assim que a instância do objeto for destruída.
Variáveis gerais: identificam aspectos do sistema, como mouse_x e mouse_y, são acessíveis de qualquer ponto do jogo, mas nem sempre podem ser modificadas via código (essas citadas só mudam conforme o mouse se move); [CONFIRMAÇÃO?]
Variáveis globais: a partir do momento que são criadas, são acessíveis de qualquer ponto do jogo (qualquer objeto e qualquer código de sala). Para criá-las, basta usar o prefixo
global. .
- Code:
global.explosion = 500; //Variável global no valor numérico de 500.
Array: também chamado de vetor ou matriz, são variáveis dimensionais.
Array monodimensional a cujo índice [0] vale 1 e índice [1] vale 50;
Array bidimensional cujo índice [2,3] vale 37. São iguais a uma tabela de batalha naval, cujas coordenadas armazenam e retornam um valor específico. A importância de arrays será vista mais tarde.
Função: comando em código que utiliza um conjunto de argumentos (de zero a vários)
instance_create(x,y,object) - função para criar instância de objeto durante o jogo. x e y são coordenadas, object é o nome.
Variáveis podem ser usadas como argumentos. Exemplo:
- Code:
{
a=50;
b=100;
instance_create(a,b,obj_avatar); // Criar instância do objeto obj_avatar com x=a e y=b.
}
Eis uma função sem argumentos:
Ainda assim, ela tem parênteses
Scripts: um conjunto de comandos que pode ser "puxado" de fora do objeto. São criados num bloquinho específico e ganham um nome.
Exemplo:
scr_MeuScript
Eles podem levar argumentos e funcionam como funções. Veja este ser executado, sem usar argumentos:
scr_MeuScript();
Supondo agora que ele leve argumentos:
- Code:
scr_MeuScript(60,90,x,y,c_white);
Agora, ele aceita como argumentos:
0: 60
1: 90
2: x (coordenada x)
3: y (coordenada y)
4: c_white (cor branca, pré-definida pelo GM)
Comentário: linhas ignoradas na execução, mas que ajudam o programador a se orientar. Existem em duas formas:
Linha por linha
- Code:
//Toda vez que eu colocar duas barras, o que vier depois é comentário.
//E, na linha seguinte, repito.
Várias linhas
- Code:
/*
Depois da barra-e-asterisco e antes do asterisco-e-barra,
tudo é comentário.
Lá, lááááá, lá, lá, lá, lááááá
Lá, lá, lá, lá, láááááá
É a música dos Smurfs!
*/
Operadores: sinais usados em operações lógicas e matemáticas.
Sinais lógicos:
- Code:
&& E
|| Ou (um, o outro ou ambos)
^^ Ou um, ou o outro; nunca os dois
Comparadores de valor:
- Code:
== Igual a
!= Diferente de
> Maior que
< Menor que
>= Maior ou igual a
<= Menor ou igual a
Operadores matemáticos:
- Code:
+ Adição
- Subtração
* Multiplicação
/ Divisão
mod Resto da divisão
= Igual (atribui valor)
Além disso, para alterar o valor de uma variável com base no seu valor original:
- Code:
a+=10; significa a=a+10
a-=1 significa a=a-1
a*=2; significa a=a*2;
a/=2; significa a=a/2;
Loops e blocos condicionais:Declaração
if: cria um programa que roda se uma proposição for verdadeira
- Code:
if a==0 instance_create(10,20,obj_qualquer);
Se a for igual a 0, cria-se o objeto de nome obj_qualquer na coordenada x=10,y=20. Não precisa usar chaves quando o bloco só tem uma declaração.
- Code:
if a==true
{
x=10;
y=5;
}
Se a for verdadeiro, então o objeto se teletransporta para as determinadas coordenadas entre chaves
- Code:
if a>=10 && b!=50
{
image_blend=c_green;
instance_create(a,b,obj_blublu);
}
Se a for maior ou igual a 10 e b não for 50, então o objeto se pinta de verde e cria um obj_blublu nas coordenadas x=a e y=b.
- Code:
if (a>10 && b==30) || (a<=10 && b==20) instance_destroy();
Se um dos dois conteúdos entre parênteses ocorrer, o objeto se destrói. Ou seja:
Tanto no caso de a ser maior que 10 e b igual a 30 quanto no de a ser menor ou igual a10 e b igual a 20, o objeto se destrói.
Declaração
elseSempre que o teste de um if der falso, pode ser definir uma alternativa com else (senão).
- Code:
if a==10
{
image_blend=c_red;
b=20;
}
else
{
image_blend=c_blue;
b=50;
}
Se a for igual a 10, o objeto se pinta de vermelho e atribui 20 a b. Senão ele se pinta de azul e atribui 50 a b.
Declaração
repeat- Code:
repeat (5) instance_create(random(400),random(400),ball);
Repete 5 vezes a criação de um objeto chamado ball, com coordenadas aleatórias até um número menor que 400 para x e y.
- Code:
repeat (5)
{
instance_create(random(400),random(400),ball);
a+=1;
}
Como acima, só que ainda acrescenta 1 ao valor de a cada vez que executar.
Declaração
while: Enquanto algo for verdadeiro, o jogo executa o bloco.
- Code:
while a<50
{
instance_create(random(400),random(400),ball);
a+=1;
}
Enquanto a<50, cria bola e aumenta a em 1.
Declaração
do: executa um bloco até que algo aconteça.
- Code:
do
{
instance_create(random(400),random(400),ball);
}
until (instance_number(ball)>50)
Faça instâncias de objeto ball até que o número de instâncias ultrapasse 50.
Declaração
for- Code:
for(declaração 1; declaração 2; declaração 3)
{
programa
}
Crie uma variável na declaração 1 com um valor inicial (ou use uma já existente atribuindo um novo valor inicial). Indique uma condição na declaração 2. Manipule o valor da variável na declaração 3. Quando a variável não mais atender a condição da declaração 2, o loop pára.
- Code:
for(i=0;i<=5;i+=1)
{
x+=1;
y-=2;
}
Seja i igual a 0. Enquanto i for menor ou igual a 5, executa o loop entre chaves e, no fim, aumenta i em 1. Quando i for maior que 5, para o loop e continua com o código a seguir.
Declaração
break: pára um bloco de loop ou bloco de programa imediatamente.
Declaração
exit: sai de um bloco de código ou de um script. Útil para finalizar eventos ou o uma janela de códigos.
Assim, se x>400, sai do bloco. Caso contrário, continua normalmente.
Na próxima, vou falar de coisas mais específicas do GM, como objeto, room, eventos etc. e como usar códigos para manipulá-los.
Recursos do Game MakerSprites: elementos gráficos em bitmap usados pelos objetos do jogo.
Sounds: músicas e efeitos sonoros em .WAV, .MID e .MP3.
Background: imagens de fundo e tiles para cenários.
----- Tileset: uma imagem bmp dividida em partes iguais onde cada pedaço serve como uma unidade para montar o cenário.
Paths: caminhos pré-determinados para algum objeto seguir na tela.
Scripts: códigos externos aos objetos que podem ser chamados por qualquer um deles ou de uma sala durante sua criação.
Fonts: fontes do jogo. O computador deve possuir uma cópia de cada arquivo de fonte utilizada pelo jogo. Tamanho e estilo são fixos.
Time Lines: sequências de programas executados por linha do tempo que podem ser executadas a partir de algum objeto.
Objects: todo e qualquer elemento ativo durante um jogo. Podem ser inimigos, o jogador, um controlador invisível de mecânica ou um coqueiro no cenário.
----- Instance: cada cópia de um objeto criada durante um jogo. O objeto é a matriz, enquanto a instância é a execução e pode ser feita várias vezes simultaneamente. Cada instância possui um valor de id único, diferente do nome do objeto.
----- Parent: um objeto determinado do qual os filhos assumem a identidade (não confundir com id). Se uma função for executada para afetar todas as instâncias de um parent, os objetos filhos são afetados, mesmo que o parent não tenha uma instância ativa no instante.
Rooms: fases ou telas, são os ambientes do jogo. Podem ser preenchidas de backgrounds, tiles ou objetos previamente ou durante o jogo.
Para um jogo rodar, é preciso ao menos criar uma room, mesmo que vazia. Na janela da room criada, em settings, existe um campo para o nome, legenda de janela, dimensões, velocidade em steps (nosso frames per second), uma opção para persistente (deixe desligada por enquanto) e um botão que dá na janela de código de criação (códigos rodados assim que o jogo entra na room).
Em backgrounds, há a possibilidade de atribuir uma cor ao fundo da sala (bom na falta de cenário, mas consome recurso à toa se não aparecer). Abaixo, 8 camadas de cenário que podem ser preenchidas com imagens simples, repetidas em tiles ou esticadas, posição de cada imagem na camada e velocidades horizontal e vertical.
Tiles permite "carimbar" unidades de tiles (azulejos) pela tela, indicando uma camada por valor numérico (número gigante de camadas possíveis, apenas indique um valor de profundidade relativa).
Em views, no caso de habilitá-los, você pode definir os espaços da tela que serão exibidos. View in room define posição inicial (canto esquerdo superior) e dimensões do view na tela. Port on screen define o espaço da tela a ser ocupado, forçando o view a ser escalado para caber nele caso seja de tamanho diferente. Object following especifica um objeto a ser seguido pelo view através da room. Hbor e Vbor indicam as margens da tela nas quais o objeto precisa estar para arrastar o view com ele. Hsp e Vsp são a velocidade com que o view segue o objeto (-1 para na mesma velocidade).
EVENTOSCrie um objeto. Temos algumas opções na esquerda: sprite inicial, visibilidade, solidez, profundidade, persistência, paternidade e máscara. Voltaremos a elas depois. Clique em Add Event. Falarei deles agora.
Evento é algo que acontece durante um step (frame). Cada evento não dura mais de um step, mas pode se repetir no seguinte. Vamos listá-los:
CREATE: Momento da criação da instância do objeto. Só ocorre uma vez. As variáveis mais importantes de cada objeto são criadas aqui.
DESTROY: A última coisa que a instância faz antes de ser apagada. Por exemplo, um inimigo pode criar um bônus assim que some após morrer.
ALARM: Após definir um alarme de tempo, o evento de alarme respectivo é executado quando o tempo chega a zero. São doze no total (0 a 11).
STEP: Os mais importantes de todos, ocorrem em todos os steps propriamente ditos. Se divide entre begin step, step e end step.
COLLISION: Define o que acontece somento no momento em que dois objetos sobrepõem suas caixas de colisão.
KEYBOARD: Um conjunto de eventos para quando alguma determinada tecla estiver sendo segurada.
MOUSE: Idem para mouse.
OTHER: Vários, como sair da sala, da view ou encostar nos limites, início e fim de jogo ou sala, fim de vida ou energia, fim de animação, fim de path, fechamento de jogo e definidos por usuário.
DRAW: Um outro evento importante, ocorre no fim de cada step e servem para desenhar algo na tela. Quando o evento draw é selecionado, a sprite do objeto não será mais desenhada automaticamente, mas um vasto número de opções estão disponíveis, como desenhar 'manualmente' a sprite. O objeto precisa estar visível para que algo seja desenhado.
KEY PRESS: Detecta se determinada tecla foi digitada desde o último step (o ato de digitar, não o de segurar).
KEY RELEASE: Detecta se determinada tecla foi solta desde o último step.
Na verdade, apenas 4 eventos são essenciais:
CREATE, STEP e DRAW, porém é quase impossível viver sem
COLLISION,
DESTROY também possibilita certa praticidade e
BEGIN STEP/ENDSTEP podem ser úteis quando algo tiver de ser definido não só após ou antes de certos comandos num objeto, mas também de todos os outros. E
DRAW, apesar de essencial, não é para o absoluto principiante - os jogos mais simples não necessitam dele.
Nesse curso, procuraremos abandonar o Drag'n'Drop - programação por ícones e inúmeras janelinhas. Centraremos nosso trabalho no seguinte recurso:
Aba Control > campo CODE > ícone EXECUTE CODEOutros comandos úteis são
COMMENT e, num primeiro momento,
MAIN 2 > GAME > RESTART, pois será útil dar reset na hora de testar, embora ele não seja tão prático num produto final (ele apaga as variáveis e só deve ser usado no caso das globais serem armazenadas num arquivo .INI).
Neste site, você pode encontrar o código correspondente para cada ícone d'n'd.
http://www.blackratstudios.com/games/DD_to_GML_7/Drag_and_Drop_Icons_and_their_GML_Equals_Ver_7.htmlGuarde-o nos favoritos pois ele será útil.
Rito de passagem:- Crie um objeto.
- Crie nele um evento DRAW. Dentro do evento, coloque um EXECUTE CODE (aba control). Abra o bloco.
- escreva:
- Code:
draw_text(0,0,'Hello, world!');
Aspas podem ser duplas ou simples, só mantenha o padrão dos dois lados.
- Crie uma room. Na aba object, escolha object0 e coloque ele em qualquer lugar da tela.
- Rode o programa clicando na seta verde de play (na barra de ferramentas).
- ??????
- PROFIT!
Considerações sobre blocos aninhadosCaso seja necessário inserir um bloco de programa dentro do outro, você pode. Isso será necessário ao usar condicionais, loops, etc. Exemplo
- Code:
if a==10
{
if x>=50
{
y+=5;
lives+=1;
}
else
{
y-=5;
lives+=2;
}
}
Ou sem aninhar, podemos usar
else if e, numa situação em que a==10 && x>=50 sejam falsos, caso ao menos a==10 seja verdadeiro,
ele executa a parte do else if
- Code:
if a==10 && x>=50
{
y+=5;
lives+=1;
}
else if a==10
{
y-=5;
lives+=2;
}
Ou seja, tudo aqui só acontece se a for igual a 10. Se x for maior ou igual a 50, o primeiro sub-bloco é executado. Senão, o segundo bloco é.
Isso também pode ocorrer:
- Code:
if a==50
{
if b==10
{
if c==5
{
draw_text(0,0,'Eu sou um imbecil!');
}
}
}
Só que é muito melhor fazer assim:
- Code:
if a==50 && b==10 && c==5
{
draw_text(0,0,'Eu não sou mais um imbecil!');
}
Use parênteses quando for usar mais de um símbolo lógico
- Code:
if a==50 && (b==10 || b==20)
{
draw_text(0,0,'Conjunção e disjunção no mesmo if.');
}
Tabela de verdadeVamos ver como funcionam valores de verdade para comparações lógicas. V significa verdadeiro (
true ou
1) e F significa falso (
false ou
0).
- Code:
&& - and / e
a | b | a && b
V | V | V
V | F | F
F | V | F
F | F | F
Quando perguntando se a && b são verdadeiros, o resultado V só sai quando ambos são verdadeiros. Em todos os outros, o bloco if não
executa (caindo num else se houver)
- Code:
|| - or / ou
a | b | a || b
V | V | V
V | F | V
F | V | V
F | F | F
Quando perguntado se a || b é verdadeiro, sempre que ao menos um deles é verdadeiro, o resultado é verdadeiro também.
- Code:
^^ - xor / ou excludente (ou um, ou outro, não ambos)
a | b | a ^^ b
V | V | F
V | F | V
F | V | V
F | F | F
No caso de a^^b, apenas quando um deles é verdadeiro, o resultado é verdadeiro. Para ambos V ou F, dá F.
Mais sobre atribuição de valoresFunções retornam valores. Isso significa que o resultado de uma função pode ser atribuído a uma variável. A criação de instâncias de objetos
retorna o número de
id da instância e isso nos será útil. Veja por quê:
- Code:
//Step de um inimigo, dentro de um bloco de programa
{
a=instance_create(x,y,obj_enemybullet);
a.direction=270;
a.speed=2;
}
Explicação:
- Na declaração 1 criamos uma instância do objeto obj_enemybullet nas coordenadas x e y da instância do inimigo. Colocamos a= na frente para que o valor da id da instância criada seja atribuído a
a.
- Na declaração 2, nós manipulamos uma variável pré-definida de nome
direction, mas é uma variável pertencente a
a, pois colocamos o prefixo
a. antes do nome da variável. Assim, a direção da instância cujo id corresponde ao valor de
a é 270°.
- Na declaração 3, fazemos a mesma coisa para a variável
speed de a: damo-lhe valor 2, assim a instância obj_enemybullet se moverá 2 pixels por step na direção que for determinada (270°).
Sobre nomesProcure nomear cada recurso conforme sua natureza. Isso facilita não só a identificação, mas possibilita dar nomes semelhantes a recursos relacionados. Por exemplo:
Sprite de uma nave inimiga: spr_enemyship ou sprEnemyShip ou SprEnemyShip etc. Qualquer coisa que lembre que isto é uma sprite.
Objeto da nave inimiga: obj_enemyship ou objEnemyShip ou ObjEnemyShip etc. Qualquer nome que lembre que este é o objeto da nave, mas não sua sprite.
Agora você não terá problemas com referências cruzadas e terá uma idéia melhor de que recursos se relacionam, no caso, a nave inimiga terá cara de nave inimiga, e não de uma ilha, porque você não tem como se confundir.