Apostila Game Maker
Apostila Game Maker
Apostila Game Maker
GAME MAKER
Verso 1.0
ESCRITORES
fUzEnRaD
Idealizador e editor
ndice
Apostila Livre - Game Maker :: 2010
1. Principais Eventos 2. Variveis globais I. Onde usar? II. Nomeando variveis globais 3. Introduo ao Draw I. Modificando cores II. Draw Point III. Draw Line IV. Draw Rectangle V. Draw Circle VI. Draw Triangle VII. Draw Text 4. Introduo aos loops I. For II. While III. Do Until 5. Movimentao bsica em plataforma 6. Movimentao bsica em TopDown I. Introduo II. Desenhando um carrinho bsico III. Criando o objeto do carro IV. Criando pistas por tiles 7. Recursos externos I. Arquivos de som II. Imagens/backgrounds III. Sprites 8. Janelas Dinmicas I. Janelas com Informaes II. Adicionando o efeito fade in/out III. Janela com botes IV. Inserir dados V. Efeitos com janelas VI. Janela mvel VII. Efeito Fade In/Out VIII. Movimento horizontal 9. Pausando o jogo
ndice
Apostila Livre - Game Maker :: 2010
10. GM3D - Primeiros passos I. O que pode ser feito em 3D no Game Maker II. A terceira dimenso! III. Construindo uma Engine 11. I. II. III. 12. I. II. III. IV. GM3D Projeo e Movimento da Cmera A funo d3d_set_projection_ext A funo d3d_set_projection_ortho Movimentando a cmera GM3D Usando Transformaes Transformaes Continuando a engine Rotao e Escalao Movimentao
Legendas:
- Possui cdigo fonte para Game Maker 8 (arquivo indicado em azul). - Captulo em reviso. - Captulo testado e revisado.
Cdigos:
1. 2. 3. 4. 5. 6. Objetos (pode ser tambm sprites, sons, fundos etc) Comandos (qualquer comando ou varivel padro do GM) Dados (nmero ou texto) Variveis Funes Comentrios (parte ignorada pelo programa)
1. Principais eventos
O Game Maker possui muitos eventos, alguns podem ser substitudos por cdigos, outros no, falarei sobre os principais eventos, o bsico que ser usado por ns, nessa apostila. As funes que sero citadas aqui so:
Os botes Delete e Change, apagam e substituem o evento selecionado respectivamente, o Add Event, mostra toda a relao de eventos disponveis, todas as opes possveis, separadas em outras sub-categorias, so elas:
Algumas opes abrem uma lista com novas opes, por exemplo o evento Mouse, essas so variaes desse evento:
Mas no nos aprofundaremos nessas sub-categorias de funes, somente em algumas delas, as quais usaremos com mais freqncia. Create Usado para iniciar as variveis, todas as variveis que sero usadas pelo objeto ao longo do jogo, devem ser indicadas nesse evento para evitar problemas futuros. Destroy Quando o objeto for destrudo executa um conjunto de funes. Alarm Indica que determinadas funes sero ativadas em algum momento do jogo, no Game Maker 8 (verso que trabalhamos nessa apostila) existe 12 eventos Alarm, para ativar um dele, tem o comando:
Alarm[n]=frames Onde n o nmero correspondente ao Alarm e o frames a quantidade de frames at ele acontecer, room_speed equivale a 1 segundo. Step Executa constantemente as funes adicionadas a ele, cuidados com as funes adicionadas nele, pode ter resultados insatisfatrios. Outside Room Aciona as funes quando o objeto sair da room, quando no for mais visvel na janela do jogo. Game Start Ao iniciar o jogo, s ser executado 1 vez na execuo do jogo.
Game End Ao sair do jogo, nesse evento comumente usamos funes para apagar arquivos ou adicionar informaes a ele. Room Start Quando a room iniciar, executa as funes, esse evento pode acontecer mais de uma vez no jogo. Room End Ao sair da room, acionado as funes inseridas nele. Draw Funes de desenho (Ver o captulo Introduo ao Draw) Press Quando uma tecla for pressionada, esse commando tem 3 variaes, Keyboard, executa enquanto a tecla estiver pressionada, Keyboard Press, executa somente 1 vez quando uma tecla for pressionada, Keyboard Released, executa quando uma tecla for solta.
2. Variveis globais
Variveis globais guardam informaes que o usuario escolhe. Essas informaes so salvas, podendo serem usadas em qualquer outra room. Por exemplo, o usuario escolhe um personagem para jogar( sobre isso que iremos trabalhar), ele clica no personagem, a informao do personagem escolhido guardado, e o personagem escolhido usado em outra room.
Coloque um sprite diferente para cada um desses objetos. Crie dois objetos: o sel_1 e o sel_2. O sprite do sel_1 deve ser o sprite do pers_1, o sprite do sel_2 deve ser do pers_2. Crie outro objeto, chame-o de selecionador. nele digite o seguinte cdigo:
if global.pers = 0 { instance_create(1,1,sel_1) } if global.pers = 1 { instance_create(1,1,sel_2) } Se a varivel global (o item selecionado) for 0, criar objeto sel_1. Se a varivel global (o item selecionado) for 1, criar objeto sel_2. Com isso ao escolher um personagem, ele ser criado na room ao iniciar o jogo.
3. Introduo ao Draw
Sempre que usarmos alguma funo desse grupo, devemos inseri-los dentro do evento Draw, caso algum dessas funes sejam inseridas em outro evento, simplesmente no funcionar. bem parecido com a inicializao de variveis, onde preciso que ela seja criada no evento create para depois ser modificada nos outros eventos. Ateno: Ao iniciar um evento no Draw, a sprite aplicada ao objeto no ser mostrada. Veremos como resolver isso mais adiante. As funes de desenho se iniciam sempre com Draw_, possvel fazer diversas coisas, como desenhar um retngulo, uma linha, um tringulo, entre vrios outros.
draw_set_color(cor) Por padro do Game Maker, se no for indicado esse comando, a cor dos elementos desenhados na tela ser preta. Para personalizar voc pode colocar por exemplo uma constante ou uma cor em hexadecimal. As cores pr-definidas so:
c_aqua //Azul piscina c_black //Preto c_blue //Azul c_dkgray //Cinza escuro c_fuchsia //Fcsia c_gray //Cinza c_green //Verde c_lime //verde limo c_ltgray //Cinza Claro c_maroon //Marrom c_olive //Oliva c_orange //Laranja c_purple //Roxo c_red //Vermelho c_silver //Prata
draw_point(x,y) No x colocamos sua posio horizontal e no y sua posio vertical. Esse comando s desenha um ponto na tela, exatamente do tamanho de um pixel. Como j foi citado, existe o comando draw_set_color que muda a cor dos comandos de draw abaixo deste, esto, vamos fazer um teste, para que o ponto fique visvel:
background_color=c_black // muda a cor do background para preto draw_set_color(c_white) //muda para cor branca draw_point(320,200) //desenha um ponto na posio 320, 200 Agora coloque este cdigo no evento draw de um objeto, insera-o na room e execute o jogo, voc perceber um minsculo ponto branco no centro da tela.
3.3 draw_line
Como o prprio nome sugere, serve para desenhar linhas com espessura equivalente a um pixel.
draw_line(x1,y1,x2,y2) Para entendermos como desenhar a linha exatamente no lugar onde queremos, necessrio saber como os cdigos funcionam. Em todos os cdigos do draw, exceto o draw_point, preciso especificar duas extremidades. O draw_line o mais fcil de compreender, porque s precisamos "dizer" ao GM, as duas extremidades da linha e ele faz o resto. Para isso necessrio saber como as coordenadas X e Y funcionam. Para explicar melhor, abaixo uma esquematizao:
Como mostrado na imagem, os dois primeiros argumentos do script x1 e y1 representam a posio x e y da primeira extremidade da linha, o mesmo com x2 e y2, que representam o x e y da segunda extremidade da linha. Existe tambm, uma verso mais avanada dessa funo, o draw_line_color, onde so informados tambm, duas cores, aplicando em suas extremidades. possvel configurar a largura da linha, mas no com uma funo padro do Game Maker, o seguinte cdigo expressa o que acontece (o comando For ser explicado mais a frente)
for (linha=0;linha<3;linha+=1) { draw_line_color(mouse_x+linha,mouse_y+linha,10+linha,10+linha, c_red,c_green) } /*linha com a espessura 3 do ponto (10,10) ate o mouse com a gradao da cor vermelha ate a verde*/ O resultado ser uma linha assim:
3.4 Draw Rectangle O draw_rectangle, desenha um retngulo e seu funcionamento muito parecido com o da linha. Assim como a maior parte das funes do draw, nesta definiremos 2 coordenadas. Esses pontos correspondem s duas extremidades do retngulo.
draw_rectangle(x1,y1,x2,y2,linha)
Os argumentos x1 e y1 servem para colocarmos as coordenadas da extremidade superior esquerda e os argumentos x2 e y2 servem para colocarmos as coordenadas da extremidade inferior direita do retngulo. Dentre os dois pontos (extremidades) que colocamos no cdigo, o Game Maker desenhar, interligando-as em ou retngulo. O argumento linha indica se voc quer desenhar somente a linha externa (True ou 1) ou se quer que seja preenchido (False ou 0)
possvel mudar a cor dessa linha, colocando-se o draw_set_color(cor) antes do cdigo. No entanto, existe uma funo mais avanada do draw_rectangle que o permite customizlo mais, preenchendo com 4 cores juntas.
draw_rectangle_color(10,10,110,110,cor1,cor2,cor3,cor4,1) Cada argumento cor representa uma ponta do retngulo: cor1: Ponta superior esquerda cor2: Ponta superior direita cor3: Ponta inferior direita cor4: Ponta inferior esquerda Por exemplo:
Exemplo 1
Exemplo 2
3.5 Draw Circle draw_circle(x,y,raio,linha) draw_ellipse(x1,y1,x2,y2,linha) draw_set_circle_precision(precisao) O draw_circle o mais fcil de se compreender. Esse, por sua vez, desenha um crculo perfeito, nada de algo oval como uma elipse. x - Posio vertical do centro do crculo; y - Posio vertical do centro do crculo; raio - O raio do crculo em pixels; linha - Determina se o crculo ser preenchido ou no. Por exemplo:
draw_circle(100,100,10,0) Resultado:
O draw_ellipse um pouco mais complicado, mas nem tanto, basicamente, voc desenha um retngulo invisvel, e o GM por sua vez, desenha a elipse coerente com as laterais desse retngulo. E j sabemos como desenhar um retngulo: E finalmente o draw_set_circle_precision, essa funo muito interessante. Ela serve para nos mostrar o quo preciso ser a resoluo do crculo. Um nmero menor, como 0 por exemplo, torna o crculo um retngulo, quanto maior esse nmero, por exemplo 100, mais redondo o crculo ficar. Deve-se colocar essa funo antes de desenhar um crculo e colocar o valor de preciso em precision. Veja a diferena entre o valor 10 e o valor 100:
Exemplo 1
Exemplo 2
Como a maioria das funes do draw, o draw_circle e o draw_ellipse possuem tambm verses para inserir cores, o draw_circle_color e o draw_ellipse_color, so muito semelhantes aos outros exemplos com cores:
draw_set_circle_precision(30) draw_circle_color(100,100,10,c_green,c_red,0)
4.1 For
mais usado quando sabemos a quantidade exata de vezes que ser executado, recomendado pra variveis seqnciais, responsvel por localizao na tela, mudana de variveis entre outros. O for comporta-se da seguinte maneira: for (inicio; condio; inclemento) { comando } Voc inicia uma varivel em incio, como pos=1, condio responsvel por garantir que o loop continue (pode ser pos<=10), se for uma condio verdadeira (true) o for continua e inclementa (pos+=1), porm se for falso (false), no faz nada e reinicia a varivel de incio (pos=1). No exemplo, vou desenhar na tela uma tabela com os 10 nomes do highscore:
Aqui foi indicado que cada a posio vertical do texto varie conforme o valor de pos, evitando que o texto fique sobreposto.
for (pos=1; pos<=10; pos+=1) { draw_text(x,y+pos*20,string(pos)+". "+highscore_name(pos))}
Parte responsvel por inserir a posio na lista, cada posio ter sua indicao, ficaria assim: "1.", "2.", "3." etc.
for (pos=1; pos<=10; pos+=1) { draw_text(x,y+pos*20,string(pos)+". "+highscore_name(pos))}
E finalmente aqui, o nome de cada posio colocado na frente da sua respectiva colocao. O resultado final ser uma tabela com os nomes dos 10 melhores jogadores em ordem e numerado de 1 a 10.
4.2 While
bastante usado pra repeties grandes, ou at infinitas, usado para executar comandos enquanto uma determinada condio for verdadeira. O comando while no muito recomendvel quando se quer controle, como posio. O comando While pode ser resumido com: while condio { comando } Por exemplo:
while instance_number(obj_inimigo)<100 { instance_create(random(room_width),random(room_height),obj_inimigo) } Nesse exemplo, sempre haver 100 inimigos na room.
4.3 Do Until
bastante similar ao comando While, porm funciona de forma diferente, ele executa funes at que a condio seja verdadeira. Sua sintax : do {
comando
} until condio Por exemplo, eu tenho um jogo, onde a vida do meu personagem se regenera sozinha, porm, bastante lenta, eu poderia resolver com o Do, assim:
do { vida+=0.01; } until vida<100 Nesse exemplo, ser executado "vida+=0.01" at que a condio "vida<100" seja falsa.
if place_free(x,y+2) gravity=1 //Se estiver livre de colisoes 2 pixels abaixo, a gravidade sera 1 else //caso contrario gravity=0 //a gravidade ser 0 Agora sim comearemos a movimentao, primeiramente faremos o personagem andar para a direita caso a tecla "direita" seja pressionada, para isso abra novamente nosso cdigo Step do objeto do personagem, e adicione o seguinte:
if keyboard_check(vk_right) //Se a tecla direita for pressionada { if place_free(x+5,y){ x+=5 } /*e se estiver livre de colisoes 5 pixels a frente, andara 5 pixels para frente*/ sprite_index=spr_player_dir } //o sprite mudara para spr_player_dir Agora faremos com que o personagem ao andar para a esquerda caso a tecla "esquerda" seja pressionada, para isso adicione isso ao cdigo do Step do nosso personagem:
if keyboard_check(vk_left) //Se a tecla esquerda for pressionada { if place_free(x-5,y){ x-=5 } /*e se estiver livre de colises 5 pixels atras, voltara 5 pixels*/ sprite_index=spr_player_esq } //e o sprite mudar para spr_player_esq Pronto, agora nosso personagem j anda para a direita e esquerda, agora faremos com que nosso personagem pule, no evento Step do nosso personagem:
if keyboard_check_pressed(vk_up) //Se a tecla cima for pressionada { if !place_free(x,y+2){ vspeed=-12 }} Nossa movimentao est feita! Agora para o personagem no passar pelos blocos, no objeto do bloco marque a opo "Solid" e no objeto do personagem, no evento Collision > objeto do bloco adicione o cdigo:
move_contact_solid(direction,12) speed=0
Agora clique duas vezes na imagem e abrir o editor, ponha Zoom 800% e siga os templates:
1. Faa um retngulo 2. Faa o desenho das rodas 3. Dentro dele faa outros dois, na vertical, que so os vidros do carro Para seu carro ficar menos "quadrado", faa como nas imagens abaixo:
friction = 0.07 Define quanto tempo ele levar para atingir velocidade 0 quando no estiver acelerando. No todo ficar assim: vel_maxima = 6 aceleracao = 0.2 freio = 0.2 curva = 2.5 friction = 0.07 Voc pode modificar e deixar como quiser. Para que as vriaveis criadas acima tenham utilidade, voc deve criar o script principal, para isso, no evento Step, arraste o Execute Code para as aes. Dentro dele deve-se colocar isso: if keyboard_check(vk_left) && speed != 0 {image_angle += curva} O que simplesmente fizemos foi, checar se a tecla esquerda (vk_left) foi pressionada e a velocidade (speed) do carro diferente de 0 (Pois um carro no pode virar parado), se sim, o ngulo da imagem (image_angle) aumentar pela var curva do carro, que definimos no create. if keyboard_check(vk_right) && speed != 0 { image_angle -= curva} Aqui o o contrrio, verificamos se a tecla direita foi pressionada e o speed diferente de 0, se sim, image angle subtrado pela curva do carro. direction = image_angle Sem isso, o ngulo da imagem mudar, mas o carro continuar andando na mesma direo. if keyboard_check(vk_up) {if speed < vel_maxima{speed += aceleracao}}
Agora checamos se a tecla pra cima foi pressionada, se sim, checamos se a var speed menor que a var velocidade mxima (Assim, impedindo que passe do limite), se sim, aumentamos a var speed pela var acelerao. if keyboard_check(vk_down) {if speed > vel_maxima*-1/2{speed -= freio}} Agora checamos se a tecla baixo foi pressionada, se sim, checamos se a var speed maior que a var velocidade mxima multiplicada por -1 dividida por 2 (Se no caso, velocidade mxima 6, a negativa -3), se sim, a var speed subtrada pela var freio. Tudo junto: if keyboard_check(vk_left) && speed != 0 {image_angle += curva} if keyboard_check(vk_right) && speed != 0 {image_angle -= curva} if keyboard_check(vk_up) {if speed < vel_maxima{speed += aceleracao}} if keyboard_check(vk_down) {if speed > vel_maxima*-1/2{speed -= freio}}
Clique em Load Background e escolha o grfico da grama. No se esquea de deixar a caixa Use as tile set desmarcada. Nossa pista ter medida de 128x128. Abra o Paint (ou qualquer programa do tipo) e crie uma imagem, seu tamanho dever ser de 128x128, como abaixo:
V em Resize e dobre o tamanho, para 256x256, agora crie um crculo na imagem, com as cores que deseja para a pista:
Salve-o, o nome pode ser qualquer um, por exemplo, curvas. Agora vamos s retas, crie imagens de 128x16 e 16x128, recomendo baixar as de baixo:
Agora no seu projeto, crie um Background, carregue a imagem do crculo, tire o fundo branco em Image > Erase a Color, e marque a opo Use as tile set, e divida por 4, como abaixo:
Resultado final:
7. Recursos externos
relativamente fcil usar recursos externos em seus jogos, fazendo-os de forma mais profissional e dinmica. Observao: Ao usar recursos externos lembre-se que mudanas externas podem ser feitas por qualquer um, entretanto jogos com a possibilidade de modificao de alguns recursos, podem fazer surgir layouts personalizados, playlist de msicas a escolha do jogador entre outros. As principais funes para manipulao de arquivos externos so:
//Backgrounds e imagens fixas background_add() background_replace() background_delete() //Sprites sprite_add() sprite_replace() sprite_delete() Eu recomendo usar o comando _add() para uso geral, no qual no existe a imagem no source, dependendo exclusivamente do arquivo externo, o _replace() recomendado quando se tem uma imagem padro caso no exista o arquivo e _delete() pra liberar a memria do jogo, fazendo-o assim ficar mais rpido. Em geral dominar essas funes com perfeio e harmonia requer estudo, tentativas e principalmente dedicao. Esses comandos so muito bons para arquivos grandes, como msicas no formato mp3 ou wav, imagens de fundo etc.
dir_mus1=working_directory+"\musica.mp3" if file_exists(dir_mus1) { musica1=sound_add(dir_mus1,3,1) if !sound_isplaying(musica1) sound_play(musica1)} Nesse caso o jogo carrega o som na varivel musica1 somente se o arquivo existir e toca somente se a msica j no est. O 3 representa o tipo de som, deve ter muito cuidado, pois dependendo do formato, no funcionar corretamente. Os tipos so: 0 Sons normais (como exploses, clicks, pulos etc) geralmente no formato .wav 1 Msica de fundo, formatos mid 2 Sons 3D (outro tipo de configurao) 3 Reproduo externa (como o mmplayer), formatos wma e mp3
sound_replace(snd_musica1,dir_mus1,3,1) Tem a mesma finalidade da funo anterior, porm agora ser substitudo o som snd_musica1 pelo arquivo no diretrio. Em um evento qualquer, voc pode indicar para liberar a memria desse arquivo, por exemplo, Alarm[0], colocando:
if !sound_isplaying(musica1) sound_delete(musica1)
7.2 Imagens/backgrounds
Muito til quando voc pretende lanar diferentes layouts pro jogo, mudando muitas vezes somente o background, isso abre uma enorme ramificao de possibilidades. Seu funcionamento muito semelhante aos sons, porm requer um pouco mais de ateno, j que as imagens devem ter o tamanho da tela e "encaixar" no designer do jogo, do contrrio voc ter um resultado "feio" visualmente.
dir_fnd1=working_directory+"\fundo.png" if file_exists(dir_fnd1) fundo1=background_add(dir_fnd1,0,1) background_index[0]=fundo1 Eu indiquei um background para o jogo apartir de um arquivo (lembre-se de ativar o "Visible when room starts" em "Background 0" nas configuraes da room). Para descartar um background, voc pode indicar uma mudana de room, fica a critrio, basta inserir:
background_delete(fundo1)
7.3 Sprites
dir_sp1=working_directory+"\sprite.png" if file_exists(dir_sp1) sprite1=sprite_add(dir_sp1,0,0,0,0,0) sprite_index=sprite1 Trabalha somente no objeto em que o cdigo est, no caso ser adicionado uma nova sprite e a anterior (caso exista) ser descartada. Cuidado ao descartar uma sprite (sprite_delete), voc deve indicar uma nova caso contrrio no ser mostrado nada.
8. Janelas Dinmicas
8.1 Janelas com Informaes
Vrias vezes, durante o desenvolvimento de um jogo, nos deparamos com um problema, as janelas do jogo, possvel usar a funo do Game Maker show_message ou get_integer, s que por mais customizvel que elas so, no fica bom, eu evito particularmente evito usar essas funes por quase nunca combinarem com o jogo. possvel fazer essas janelas com GML, assim abrindo uma imensa gama de possibilidades, como efeitos, opes, customizao etc, basta saber aproveit-las. at simples trabalhar com janelas dinmicas, em geral saber posicionamento e configurar corretamente a coordenada da origem das sprites. Pra comear, sempre bom saber o que voc pretende fazer, a posio das janelas etc, pra quem estar iniciando, recomendvel fazer efeitos simples, mais "quadrados", pois ajuda a respeitar a posio, mas com o tempo voc vai posicionar no olho.
Essa a rea que eu vou trabalhar, uma imagem de 324x191 pixels, separada em pequenos quadrados de 10 pixels. A segunda parte determinar a rea das informaes que sero adicionadas nessa janela, como feito na imagem abaixo:
Feito isso, voc atribui algum efeito, imagem de fundo, colorizao, enfim, essa parte vai da criatividade de cada um, nesse caso eu fiz uma montagem bem simples, no prprio editor de sprites do Game Maker, embora simples, ficou bem agradvel.
Se voc quiser adicionar textos na janela, fica mais fcil pro jogador identificar o que est contido nas regies, no meu caso eu vou colocar s "Informaes", "Drago" e "Personagem", que vai mostrar informaes de um RPG (um exemplo):
Informaes Voc est no reino de Dacrons. Encontre o treinador do centro da cidade para que ele te ajude a treinar seu novo drago. Personagem Drago Glacial XP: 278/350 Drago
(Poderia ser uma imagem fixa, mas no caso o drago ser mudada ao passar do jogo, por isso tem que ser uma imagem separada) Finalizamos ento a parte grfica da janela, entra agora a programao. Ser usado somente 1 objeto, assim fica mais fcil atribuir efeitos de movimento, fade, ou qualquer outro.
No evento Create do objeto, temos que identificar as variveis que ser usada na janela, no caso so:
tahoma=font_add("Tahoma",8,0,0,32,127) tahoma_n=font_add("Tahoma",8,1,0,32,127) //As fontes da janela nome_dragao="Dragao Glacial" exper_atual=278 exper_max=350 img_dragao=sp_glacial //Personagem some=0 msg_missao_atual="Voce esta no reino de #Dacrons.##Encontre o treinador do #centro da cidade para que #ele te ajude a treinar seu #novo dragao." //Missao atual Essas variveis so fixas, mas em um jogo elas devem se direcionadas para ler as informaes ao decorrer do jogo. Mudando a misso, a experiencia etc. Com as variveis j fixadas, vamos para o evento Draw, que onde toda a "mgica" feita, primeiro vamos mostrar a janela do jogo ( uma sprite chamada sp_janela).
draw_sprite_ext(sp_janela,0,x,y,1,1,0,c_white,image_alpha) //ser mostrada na posio que for colocada na tela draw_sprite_ext(img_dragao,0,x+209,y+19,1,1,0,c_white,image_alpha) //agora a imagem do drago, na rea que ele deve aparecer Ateno: Com o tempo vai ser muito mais fcil determinar a posio dos itens na janela, uma soluo fcil e rpida, voc colocar a janela na posio 0x0 dentro da room e usar uma funo no mouse, pra mostrar a posio X e Y atual:
draw_text(mouse_x,mouse_y,"x="+string(mouse_x) + " y=" + string(mouse_y)) Com isso voc sabe o valor que deve ser adicionado a X e Y da janela para que fique no lugar correto. Falta agora as informaes em texto:
draw_set_font(tahoma) draw_set_halign(0) draw_text_color(x+26,y+24,msg_missao_atual,c_white,c_silver,c_white, c_ltgray,image_alpha) //As informaes sobre a fase draw_set_font(tahoma_n) draw_text_color(x+217,y+138,nome_dragao + "#XP: " +
if if if if
keyboard_check_pressed(ord('S')) some=1 keyboard_check_pressed(ord('A')) some=0 image_alpha<1 and some=0 image_alpha+=0.05 image_alpha>0 and some=1 image_alpha-=0.05
Esse cdigo far com que ao pressionar a letra S do teclado, a janela desaparece e ao apertar A ela reaparece, um efeito bem simples, mas bem ocasional, pode ser usado em diversos tipos de jogos. Por fim, o resultado final ser:
Voc pode ver a engine desse tutorial, o arquivo jan_dinamica.gmk. 8.3 Janela com botes Agora vou mostrar como posicionar botes de opo, bem parecido com o esquema padro do Windows. Um janela com Ok, Ok/Cancelar e Sim/No. Antes de tudo, vamos criar a janela, o esquema o mesmo do outro, fazer primeiramente um layout, s pra posicionar corretamente os itens nela.
Esse o espao que ser usado para criar a janela, existem diversos programas especializados para edio e criao de imagens como GIMP e Photoshop, mas possvel fazer no prprio editor de imagens do Game Maker. O prximo passo determinar a regio onde ser disposto o texto e os botes.
Feito isso e usando seu editor de imagens preferido, crie uma janela com alguma imagem de fundo, com algum efeito, sombra, iluminao, enfim, aqui a sua imaginao manda.
Nesse exemplo eu fiz um efeito bem simples de metal, com uma textura bem leve, combina com vrios tipos de jogos. O espao da mensagem da janela eu destaquei para diferenciar das outras reas, mas fica a critrio de cada um, eu particularmente gosto de efeitos assim, so simples, mas muito agradveis.
A mesma coisa foi feita com os botes, colocando o mesmo efeito, mas em um tom diferente, a terceira imagem a segunda invertida horizontalmente e verticalmente (textura aplicada depois). Ao envi-las para o Game Maker, configure a regio de origem dessas sprites, do boto para 29x10 e da Janela para 133x46, como mostrado nas imagens abaixo:
Como exemplo, as 3 janelas que sero criadas nesse tutorial so: Boto: Ok Texto: "Para que as configuraes sejem aceitas, necessrio reiniciar o Jogo." Boto: Ok/Cancelar Texto: "Voc tem certeza que deseja encerrar o aplicativo? Seu jogo ser perdido." Boto: Sim/No Texto: "O arquivo selecionado j existe. Deseja substituir?" Terminado a parte grfica, vamos agora para a programao. Em um novo objeto, chamado botao_ok, ser configurado as opes da sprites no Mouse Left Pressed, Mouse Left Released, Mouse Enter e Mouse Leave, pra respectivamente image_single=2, image_single=1, image_single=1 e image_single=0. E no evento create ser indicado somente:
image_single=0 //Faz com que o objeto inicie com a sprite parada tahoma_n=font_add("Tahoma",8,1,0,32,127) //Seta a fonte usada no objeto No evento Draw inserimos:
draw_set_font(tahoma_n) //Chama a fonte tahoma_n draw_set_halign(1) //Alinhamento horizontal no centro (1) draw_set_valign(1) //Alinhamento vertical no centro (1) draw_sprite_ext(sprite_index,image_single,x,y,1,1,0,c_white, image_alpha) //Mostra a sprite do botao draw_text_color(x+1,y,"Ok",c_gray,c_silver,c_gray,c_silver, image_alpha) draw_text_color(x,y-1,"Ok",c_black,c_dkgray,c_black,c_black, image_alpha) //Mostra "Ok" em preto com uma sombra cinza
O mesmo com os botes Cancelar, Sim e No, no Gm possvel duplicar um objeto, o que ajuda bastante, mas lembre-se de alterar o texto que ser mostrado no Boto, substituindo por "Cancelar", "Sim" e "Nao" respectivamente.
necessrio agora fazer um novo objeto, com a sprite da janela para controlar os botes e posicion-los corretamente. No evento Create desse novo objeto:
instance_create(x,y,botao_ok) //Cria o botao iniciar instance_create(x,y,botao_cancelar) //Cria o boto Cancelar tahoma_n=font_add("Tahoma",8,1,0,32,127) //Seta a fonte do objeto mensagem="Voce tem certeza que deseja#encerrar o aplicativo?##Seu jogo sera perdido." //Determina a mensagem a ser mostrada Ao criar os botes eles sero posicionados na posio X e Y da janela, mas no esto alinhados, isso ser feito no evento Step desse objeto:
with instance_nearest(x,y,botao_ok) { x=other.x-80 y=other.y+61 } /*Com o objeto botao_ok mais prximo, posicione em -80 e +61.*/ with instance_nearest(x,y,botao_cancelar) { x=other.x+80 y=other.y+61 } /*Com o objeto botao_cancelar mais proximo, posicione em +80 e +61.*/
draw_set_font(tahoma_n) //Define a fonte draw_set_halign(1) draw_set_valign(1) //Alinhamento horizontal e vertical no centro (1) draw_sprite_ext(sprite_index,image_single,x,y,1,1,0,c_white, image_alpha) //Desenha a sprite da janela draw_text_color(x,y,mensagem,c_black,c_dkgray,c_black,c_black, image_alpha) //Desenha o texto na janela Pra posicionar um boto no centro:
with instance_nearest(x,y,botao_ok) { x=other.x y=other.y+61 } As outras janelas so exatamente a mesma coisa, s muda o texto e o boto delas, possvel fazer algum efeito de movimento ou de Fade in/out (como feito no tutorial anterior), tornando-as mais profissional. O grande diferencial dessas janelas que elas no interferem no funcionamento do jogo e possvel atribuir uma grande gama de possibilidades. E finalmente o resultado ser:
Veja jan_dinamicas2.gmk para entender melhor essa parte do tutorial. Observao: A engine tem as 3 janelas concludas, separadas em rooms diferentes, ajuda no estudo, pra colocar as funes desejadas, basta inser-las no evento "Mouse Released", como game_end(), room_goto_next(), depende da situao.
8.4 Inserir Dados Essa parte do tutorial ser a mais usada provavelmente, pode ser usada quando o jogador perde, para adicionar no Highscore do jogo, ou em um jogo multiplayer onde necessrio inserir dados como Nick, IP etc. Ou at mesmo para usar em um chat em um jogo online, tem diversas utilidades. Ateno: essencial seguir esse tutorial com a engine aberta, algumas funes ser mais bem entendidas se for feito um acompanhamento (jan_dinamicas3.gmk). Novamente vamos usar a grade separada em pequenos quadrados, nesse exemplo eu vou fazer uma janela para conexo de um jogo multiplayer, haver 3 reas para inserir dados (Nick, Seu IP e Conectar ao IP) e 3 botes (Conectar e Cancelar), sobre os botes, foi visto no exemplo anterior (Janelas com botes), por tanto no vou me aprofundar tanto nessa parte do tutorial.
O padro o mesmo, distribuindo regularmente a posio das regies em uma rea quadriculada, impede os erros de simetria e alinhamento.
Pra finalizar eu usei uma textura de rochas e as reas de dados um prateado bem discreto e na janela um sombreamento bem claro (feito no editor do Game Maker), nesse exemplo eu inseri os botes direto na janela, diferente do exemplo anterior, onde eram sprites, isso facilita um pouco, mas impede que os botes sejem modificados de posio mais tarde.
Os botes Em relao ao exemplo anterior, sobre os botes, esse ter novas caractersticas, o funcionamento o mesmo, usando os eventos Left Pressed, Mouse Enter etc, no caso o boto Conectar vai acender verde quando apontar para ele e o boto Cancelar vermelho, um efeito bem discreto, mas que fica muito bom.
if image_single=0 draw_text_color(jan_mplayer.x+208,jan_mplayer.x+68,"Conectar", c_black,c_dkgray,c_black,c_black,image_alpha) else draw_text_color(jan_mplayer.x+208,jan_mplayer.x+68,"Conectar", c_lime,c_green,c_black,c_green,image_alpha) Traduzindo, se o mouse estiver em cima do boto (image_single diferente de 0) a cor do texto ser vermelho (ou verde, se for o boto conectar). A localizao dos pontos foram feitas de forma diferente, nesse exemplo eu criei um objeto, e no evento draw dele eu coloquei uma funo para mostrar a localizao do pontos X e Y, ento eu os posicionei no lugar correto, onde devero aparecer, facilitou bem mais do que
a tcnica anterior, onde a funo para mostrar a coordenada era inserida no mouse_x e mouse_y, o resultado foi esse:
Com a origem da janela em 0x0 e na posio 0x0 na room, esse o valor que eu terei que somar ao x e y da janela, para posicionar corretamente. Os valores seguidos no tutorial so esses ai. No evento Create do objeto jan_mplayer, foi indicado vrias variveis, as globais so o texto que estamos modificando, so: o nick, o ip e o ip para conectar, no caso eu coloquei uma funo para detectar o ip da mquina, esse nmero voc indica ao seu amigo para jogar em modo multiplayer e o outro ip, um string fixa, com o ip zero da mquina (127.0.0.1).
instance_create(x,y,botao_conectar) instance_create(x,y,botao_cancelar) instance_create(x,y,barra1) instance_create(x,y,barra2) instance_create(x,y,barra3) //Cria os botoes e as regioes do texto lucida=font_add("Lucida Console",8,0,0,32,127) global.nick="Fuzenrad" global.seuip=mplay_ipaddress() global.conectar="127.0.0.1" maximo=15 //Quantidade maxima de caracteres cursor="|" t=1 alarm[0]=5 escolhe=0 Eu optei por substituir a fonte pela Lucida Console, pois uma fonte em que o tamanho fsico que cada letra ocupa indiferente de que letra seja (W ou l), isso possibilita alinhar corretamente e determinar o espao para o nmero de caracteres.
if keyboard_check_pressed(vk_backspace) global.nick=string_delete(global.nick,string_length(global.nick),1) if maximo-string_length(global.nick)>0 { if keyboard_string!="" { global.nick=string_insert(keyboard_string,global.nick,string_length( global.nick)+1) keyboard_string="" }} else keyboard_string="" muito simples, ele s apaga o texto (com a tecla Backspace), ou insere, no possvel copiar, colar ou selecionar, eu poderia ter me baseado em algum exemplo por ai, mas bastante extenso as funes para realizar isso, e acredito que para um tutorial, somente a funo bsica de edio de texto j muito til (que apagar e escrever). Nos 3 objetos da rea para inserir texto, ao clica, ele altera o valor da varivel jan_mplayer escolher, para assim selecionar qual janela o cursor ir editar (caso contrrio, teramos um resultado indesejado). O evento draw do objeto jan_mplayer responsvel por mostrar todos os itens da janela, organizando-os de forma mais fcil.
draw_set_font(lucida) draw_set_halign(0) draw_set_valign(1) draw_sprite_ext(sprite_index,image_single,x,y,1,1,0,c_white,image_al pha) if escolhe=1 { mostra_nick=global.nick+cursor } else mostra_nick=global.nick if escolhe=2 { mostra_ip=global.seuip+cursor } else mostra_ip=global.seuip if escolhe=3 { mostra_conectar=global.conectar+cursor } else mostra_conectar=global.conectar draw_text_color(jan_mplayer.x+28,jan_mplayer.y+30,mostra_nick, c_black,c_dkgray,c_black,c_black,image_alpha) draw_text_color(jan_mplayer.x+28,jan_mplayer.y+68,mostra_ip, c_black,c_dkgray,c_black,c_black,image_alpha) draw_text_color(jan_mplayer.x+28,jan_mplayer.y+108,mostra_conectar, c_black,c_dkgray,c_black,c_black,image_alpha)
No caso da varivel cursor, o evento Alarm responsvel por alterar entre "|" e "" (vazio), se cdigo :
switch t=0 { case 0:{cursor="|" t=0} break; case 1:{cursor="" t=1} break; } alarm[0]=5 Ele alterna a varivel t, e para o resultado 0, mostra o cursor, para o resultado 1, oculta. E por fim, o evento Destroy, responsvel por destruir todos os objetos relacionados a janela, evitando problemas futuros.
with instance_nearest(x,y,botao_conectar) { instance_destroy()} with instance_nearest(x,y,botao_conectar) { instance_destroy()} with instance_nearest(x,y,barra1) { instance_destroy()} with instance_nearest(x,y,barra2) { instance_destroy()} with instance_nearest(x,y,barra3) { instance_destroy()} O resultado final, creio eu, foi o melhor dos outros 2 exemplos, o boto ficou bem personalizado com colorao, com esse sistema possvel fazer, como eu j citei, a rea onde ser inserido o nome do jogador para adicionar em um highscore, ou no menu principal, uma janela pro jogador informar o nome, no sei, fica a critrio.
x_relativo=x-mouse_x
y_relativo=y-mouse_y Atribuimos isso ao evento Step, para que seja uma varivel atualizada. Agora em um evento do mouse, por exemplo Left Buttom:
x=x_relativo+mouse_x y=y_relativo+mouse_y Para mover vrios objetos ao mesmo tempo, temos que usar a funo with, que controla outros objetos:
with instance_nearest(x,y,botao1) { x=other.x-80 y=other.y+75 } Com o objeto botao1 mais prximo, mova-o, ao mesmo tempo que o boto corretamente posicionado na janela. Veja jan_movel1.gmk.
image_alpha=-0.5 apaga=0 A varivel image_alpha inicia em -0.5 para que tenha uma diferena entre a criao e o surgimento dela na tela, bem mnima, milisegundos. E iniciamos a varivel apaga, que usaremos mais adiante. Do mesmo modo que fizemos no exemplo anterior, controlando objetos com o with, mas desta vez com o image_alpha:
if image_alpha<1.5 and !apaga{ image_alpha+=0.05 with instance_nearest(x,y,botao1) image_alpha=other.image_alpha} if image_alpha>0 and apaga{ image_alpha-=0.05 with instance_nearest(x,y,botao1) image_alpha=other.image_alpha}
Quando a varivel apaga for true (ou 1) e image_single for maior que zero ou quando apaga for false (ou 0) e image_single for menor que 1.5, a janela desaparecer e aparecer respectivamente. No evento Left Released do objeto botao1, adicionamos:
jan_movel.apaga=1 Para indicar que ao ser pressionado a janela desaparea. Confira a engine jan_fadeinout.gmk.
x_antigo=x move=1 x=room_width+150 Lembrando que room_width a largura da room e 150 aproximadamente a metade da largura do objeto, assim o objeto salta para uma posio fora da janela, para ento se mover. Para finalmente mover a janela, no evento Step usamos:
if x>x_antigo and move=1 x-=10 else move=0 if x<=x_antigo and move=1 x=x_antigo Isso indica que enquanto a posio atual do objeto no for menor ou igual a posio inicial do objeto (associada x_antigo) ser subtrado 10 pixels a cada frame. Para maiores informaes veja a engine jan_movel2.gmk.
9. Pausando o jogo
Em quase todos os estilos de jogos, necessrio ter um Pause, muitas vezes pelo Game Maker no ter uma funo pr-definida pra isso, fica um pouco difcil fazer com outras funes. Embora no de forma prtica, o Game Maker possui uma maneira para "Travar/Pausar" o jogo:
screen_refresh() keyboard_wait() io_clear() Cada uma individualmente, desempenha funes especficas, no necessariamente ligadas a um sistema de Pause. O screen_refresh atualiza a janela do jogo. keyboard_wait faz com que tenha uma espera do teclado e nenhuma tecla pressionada seja considerada. E por ltimo io_clear, IO quer dizer Input/Output (Entrada/Sada) e tem a funo de zerar a varivel de tecla ou mouse informado anteriormente. Basicamente, basta adicionar o cdigo acima citado, em um evento do tipo Keyboard (Veja captulo 1), preferencialmente P para que ao ser executado, o jogo pause. Para teste, vamos fazer aparecer uma imagem com a mensagem "Pause", quando o jogo estiver pausado.
Primeiro criamos um evento qualquer, com algum movimento, apenas para representar que o jogo est em andamento, pode ser um movimento circular, uma sprite com vrias subimagens etc, nesse exemplo eu usei no evento Step o cdigo:
image_angle+=21 direction+=5 speed=3 Isso faz com que o ngulo da imagem aumente constantemente 25, a direo 5 e o speed seja constantemente 5, gerando um movimento circular regular. Em um outro objeto, ob_pause, por exemplo, indicamos algumas coisas:
if keyboard_check(ord('P')) { mostra=1 draw_sprite(sprite_index,0,x,y) screen_refresh() keyboard_wait() io_clear()} else mostra=0 Fazendo com que ao pressionar a letra P, mostre tenha agora o valor 1, mostre a sprite e finalmente pause o jogo, ao soltar a tecla P, mostra volta ao seu valor inicial, que 0. E finalmente no evento Draw:
if mostra draw_sprite(sprite_index,0,x,y) O jogo ser pausado com a letra P, sem interferir nos objetos e sem complicaes, a imagem pode ser custumizada, pode ser usado em qualquer tipo de jogo, no trs problemas de execuo. Confira a engine desse captulo: pause.gmk.
O 3D no Game Maker ainda bem limitado e falta muitas ferramentas que por padro deveriam estar disponveis. Embora tudo isso possa ser contornado com uso de DLLs e scripts que tem aos montes feitos pelos prprios usurios do programa, voc precisara sempre pesquisar para expandir o que pode ser feito em seu jogo. O computador do programador deve ter pelo menos uma boa placa de vdeo pois o uso de muitas texturas de tamanho grande podem no funcionar causando o famoso erro Unexpected error occurred when running the game que na maioria das vezes causado porque o jogo est usando um recurso da placa de vdeo que no existe ou usando mais memria do computador do que ele realmente tem. Considerando tambm que no vamos fazer uma obra de arte que custar milhes e centenas de pessoas para ser feita em trs anos... como dizem: O limite e a criatividade do criador.
10.2
A terceira dimenso!
Existem muitos tipos de conceitos para explicar o 3D, mas falarei apenas do mais usado. A viso da tela apenas com o X e Y aparenta estar de p, onde X vai para os lados e Y para cima ou para baixo.
Mas ao inserir a terceira dimenso percebemos que na verdade a viso esta deitada, pois Z representa a profundidade.
Quanto maior o Z mais alto o ponto vai estar e quanto menor mais baixo ou profundo o ponto. A terceira dimenso no tem nada de complicado. Basta lembrar que ela a profundidade, volume ou altura enquanto as outras duas so a largura e o comprimento.
10.3
Agora vamos iniciar uma engine. A cada aula diferente voc ira complet-la cada vez mais at que o resultado final seja algo parecido com um jogo de corrida. Por enquanto vamos s aprender a desenhar um cubo na tela. Abra o GM e vamos comear! Todo jogo precisa de algo que controle o que o jogador ir ver. Crie um novo objeto e nomeio como objCamera. Agora temos que ativar o modo 3D e definir as configuraes iniciais. No evento Create do objCamera coloque: d3d_start(); Isso inicia o modo 3D do Game Maker d3d_set_perspective(true); Ativa a visualizao em perspectiva. Isso reala a noo de profundidade dos objetos. d3d_set_hidden(true); Esse muito til pois far com que todos as superfcies desenhadas atrs de outro objeto no apaream.
d3d_set_fog(true,c_white,1,1200); Fog uma espcie de neblina. Todo que estiver a 1200 pixels da viso do jogador ser escondido por ela. d3d_set_culling(false); O culling faz a parte de dentro dos objetos, ou seja, o lado de trs das textura no serem desenhados. Se a cmera olhar de dentro de um cubo, as paredes do cubo ficam invisveis. d3d_set_shading(false); Shading significa sombreamento. Ele melhora a qualidade do efeito da luz nos objetos mas como no usar iluminao nesse exemplo deixe-o como false. texture_set_interpolation(true); Melhora a qualidade das texturas. draw_set_color(c_white) Defina a cor de desenho como branco (c_white). z=48; Todos os objetos tem uma varivel x e y por padro. Mas o z ter sempre que ser criado manualmente. Defina como 48 porque a cmera ficara um pouco acima do cho. Agora preciso definir como o jogo vai ser visualizado. No evento Draw digite: d3d_set_projection(x,y,z,obj1.x,obj1.y,obj1.z,0,0,1); Vou explicar essa funo de um jeito mais completo na prxima aula pois o objetivo aqui apenas ensinar a desenhar um cubo na tela. Agora crie um novo background. Ele vai ser a textura do objeto. Desenhe qualquer coisa. Servira apenas para visualizar melhor os lados do cubo. Eu fiz este:
Agora crie outro objeto. Ele ser o cubo. Nomeio como obj1. No evento Create defina: z = 0; A varivel z. tex = background_get_texture(background0); Essa funo retorna o lugar na memria do computador onde a textura do background0 est armazenada. Agora no evento Draw: d3d_draw_block(x-16,y-16,z-16,x+16,y+16,z+16,tex,1,1) Com isso desenho cada lado com 32 pixels, defino a textura dele e os dois ltimos valores so quantas vezes a textura vai se repetir nas paredes do cubo. Pronto! Coloque o jogo pra rodar e veja o resultado. Veja a engine desse captulo, arquivo GM3D 01.gmk.
11.1
A funo d3d_set_projection_ext
Existem duas funes que usamos para definir como o mundo ser visto: d3d_set_projection(xfrom,yfrom,zfrom,xto,yto,zto,xup,yup,zup); d3d_set_projection_ext(xfrom,yfrom,zfrom,xto,yto,zto,xup,yup,zup,ang le,aspect,znear,zfar); A primeira a forma simples e a segunda a forma estendida da funo. Iremos usar apenas a segunda. Fazer com que entendam cada argumento ser bem complicado, mas eu gosto que tudo seja explicado ento prestem bastante ateno e faam testes com cada parmetro.. d3d_set_projection_ext(xfrom,yfrom,zfrom,xto,yto,zto,xup,yup,zup,ang le,aspect,znear,zfar) xfrom,yfrom,zfrom,xto,yto,zto from significa de e to para. Os trs primeiros argumentos so os pontos da cmera, ou seja, o lugar de onde se olha e os trs ltimos o lugar para onde esta se olhando. Por exemplo: Voc esta no quarto olhando para o computador. A posio dos seus olhos representam xfrom,yfrom,zfrom e a posio do computador representa xto,yto,zto. xup,yup,zup esses argumentos so definidos apenas como false ou true. Neles voc especifica o eixo em que a projeo gira. Exemplo: Voc ainda est olhando para o computador. Levante ou abaixe a cabea. Pronto! Voc acabou de girar a viso em torno do eixo y. Agora mexa a cabea para direita ou para a esquerda. Pronto! Voc acabou de girar a viso em torno do eixo z. Girar em torno do eixo x seria como rodar a cabea em torno de si mesma olhando sempre pra fentre. Marque como true os eixos que a cmera vai gira. O padro usado 0,0,1, ou seja, ira girar em torno do eixo z.
angle este no tem nada a ver com o ngulo da viso e muita gente se confundi com ele. Aqui voc deve definir a largura da cmera em graus. Exemplo: As lentes dos culos so medidas em graus lembra? Quanto maior o grau, mas as imagens so aumentadas. Voc j viu aquelas cmera que quanto se gira a lente o zoom aumenta ou diminui? Ento! O efeito desse argumento o mesmo. Quanto maior o valor de angle, maior vai ser o zoom natural da projeo. Um padro razovel 45 mas eu estou usando 90 em meus projetos. aspect defini o aspecto da tela. No h muito o que explicar... Se voc esta usando uma dimenso de tela padro (640x480, 1024x768...), qualquer valor sem ser a diviso desses tamanho causara distoro na imagem. Defini-o como 640/480 ou simplesmente 1.3. znear,zfar de znear a zfar a regio que ser desenhada pela cmera. Por exemplo: znear 1 e zfar 10000. Tudo que estiver entre o pixel 1 e o pixel 10000 da projeo ser desenhado. Tudo que estiver fora dessas coordenadas no ser desenhando.
Nessa figura a primeira linha vertical representa o znear e a segunda linha vertical o zfar. Tudo o que h na parte azul ser desenhado e tudo o que h na parte cinza no ser desenhando. O padro znear = 1 e zfar = 32000.
11.2
A funo d3d_set_projection_ortho
Se voc quer desenhar coisas bidimensionais em modo 3D? Ento ter que usar isso. Viso ortogonal nada mais do que a projeo das imagens ignorando a profundidade delas, ou seja, o valor z. Seria como desenhar um modelo 3D com todas as suas coordenadas z iguais a zero. Ele ficaria achatado. Sem profundidade.
Essa funo extremamente til, pois podemos desenhar textos e imagens na tela sem dificuldades. d3d_set_projection_ortho(x,y,w,h,angle) x,y,w,h essa a regio ou tamanho da tela. Note que se for diferente do tamanho da view o que for desenhado na tela vai se esticar em relao a view. angle gira o que for desenhado. O ponto de origem por padro o meio da area que voc definiu. Para desenhar um texto na tela voc pode fazer da seguinte forma: draw_set_color(c_black); d3d_set_projection_ortho(0,0,view_width,view_height,0); d3d_set_hidden(false); draw_text(10,10,'FPS: ' + string(fps)); d3d_set_hidden(true); Essa funo deve vir sempre antes de d3d_set_projection_ext ou a cena no ser desenhada direito.
11.3
Movimentando a cmera
Agora hora de aprender como movimentar a cmera no mundo. Vamos adicionar um exemplo de viso em terceira pessoa onde o personagem totalmente enquadrado pela cmera no projeto da aula anterior. Depois explicarei como adaptar isso para primeira pessoa que ver o mundo como se estiver com os olhos do personagem. Abra a engine que comeamos na aula 1. Voc tambm pode baixar o source clicando aqui. Crie um novo background que ser a textura do cho.
Abra o obj1 e defina outra varivel para a textura do cho: tex2 = background_get_texture(background1); No evento Draw:
d3d_draw_floor(0,0,0-16,room_width,room_height,0-16,tex2,5,5); Isso vai desenhar um cho do tamanho da room e embaixo do cubo. Agora abra o objCamera e vamos definir todos as variveis necessrios para controlar o movimento no evento Create: // Movimento da camera z = 0; // ponto z dx = 0; // armazena movimento x da cmera dy = 0; // armazena movimento y da cmera dz = 0; // armazena movimento z da cmera px = 0; // ponto x para onde se esta olhando py = 0; // ponto y para onde se esta olhando pz = 0; // ponto z para onde se esta olhando zoom = 400; zang = 0; // angulo horizontal da camera yang = 0; // angulo vertical da camera // Definir posio do mouse window_mouse_set(200,200); // Sem cursor window_set_cursor(cr_none); Agora crie um evento Step e: Primeiro deve-se achar os ngulos da cmera. o movimento do mouse que vai modar os ngulos ento precisamos saber o quanto e para onde ele esta se movendo. // Definindo angulos a partir do mouse zang-=(window_mouse_get_x()-200)/8; yang-=(window_mouse_get_y()-200)/8; window_mouse_set(200,200); yang=median(yang,-89,89); zang igual a posio x do mouse -200 dividido por 8. Isso retorna quantos pixels o mouse se moveu em x. yang igual a posio y do mouse -200 dividido por 8. Isso retorna quantos pixels o mouse se moveu em y. O valor 8 a sensibilidade do mouse. Quanto menor mais rpido o movimento vai ficar. A funo window_mouse_set defini a posio do mouse novamente depois de j achar os ngulos. A ultima linha de cdigo faz com que yang nunca passe de -89 a 89, ou seja, quanto a cmera estiver em cima ou embaixo do objeto seu ngulo vertical no mudar mais. J temos os ngulos vertical e horizontal definidos. Agora precisamos saber o quanto os pontos x,y e z da cmera teriam que mudar para que possa girar em torno do personagem.
// Animao da camera // calculando movimento dos vetores da camera dx=cos(degtorad(zang)); dy=-sin(degtorad(zang)); dz=tan(degtorad(yang)); // normalizar vetores // torna movimento da camera totalmente esferico. m=sqrt(sqr(dx)+sqr(dy)+sqr(dz)); dx/=m; dy/=m; dz/=m; Coseno, seno e tangente so operaes matemticas para achar pontos de acordo com um ngulo. Convertemos os graus em radianos com a funo degtorad(ang). cos retorna quantos pixels o x ter que se mover para estar naquele ngulo. sin retorna quantos pixels o y ter que se mover para estar no mesmo ngulo que x (ngulo vertical). E tan retorna quantos pixels o z ter que se mover para estar de acordo com o ngulo vertical. Por ultimo em tenho que normalizar dx, dy e dz para que o movimento gire de forma perfeitamente esfrica em torno do personagem. No tem muito o que explicar disso. Aquilo uma operao para no deixar que o zoom mude automaticamente dependendo do ngulo. Agora s definir as novas coordenadas da cmera de acordo com dx, dy e dz. // Calculando posio da camera no mundo x = obj1.x+dx*zoom; y = obj1.y+dy*zoom; z = obj1.z+dz*zoom; // Zoom if keyboard_check(vk_add) zoom += 4; if keyboard_check(vk_subtract) zoom -= 4; Ao multiplicar os valores que acho com cos, sin e tan eu estou adicionando uma distancia ao movimento. Essa distancia o zoom que vale 400 pixels. A cmera ficar a 400 pixels do personagem. Adicionei tambm algo para aumentar e diminuir o zoom apertando + ou - no teclado.
Finalize o cdigo do evento Step definindo o lugar para onde o cmera vai olhar que no caso a posio do obj1. // px py pz Movimento no personagem = obj1.x; = obj1.y; = obj1.z;
Abra o evento Draw do objCamera, apague o cdigo l e defina uma nova projeo: d3d_set_projection_ext(x,y,z,px,py,pz,0,0,1,90,1.3,1,32000); Adicione um movimento simples para o obj1. Crie um evento Step nele: if if if if keyboard_check(ord('W')) keyboard_check(ord('S')) keyboard_check(ord('A')) keyboard_check(ord('D')) y y x x -= += -= += 4; 4; 4; 4;
Pra finalizar defina a velocidade da room como 60. Se voc quiser fazer um viso em terceira pessoa simples. Basta inverter os pontos xfrom, yfrom, zfrom, xto, yto, zto d3d_set_projection_ext(px,py,pz,x,y,z,0,0,1,90,1.3,1,32000); No se esquea de tirar o cdigo que desenha o cubo porque seno a viso vai ficar tampada pela parte de dentro do cubo. Veja a engine desse captulo, arquivo GM3D 02.gmk.
12.1
Transformaes
Para rotacionar ou escalar um objeto voc precisara usar as transformao D3D. Todas as suas funes comeam com a expresso d3d_transform_. Primeiro voc precisa definir o que ser transformado seno os efeitos sero aplicados no mundo todo. Para isso existe uma funo que identifica o que esta sendo desenhado e aplica os efeitos apenas neles. Ela a d3d_transform_set_identity(). Outra coisa importante que as transformao so aplicadas usando o ponto de origem da room (que 0,0,0 para x,y,z) e no o do objeto, ou seja, quanto voc rodar um modelo ele vai girar em torno do ponto 0 da room e no em torno de si mesmo (como a Terra girando em torno do Sol). Para resolver isso alem de usar d3d_transform_set_identity voc tambm usar a funo d3d_transform_add_translation(x,y,z); que defini que a transformao ser aplicada em torno dos argumentos x,y,z. Veja um exemplo: d3d_transform_set_identity(); d3d_transform_add_translation(x,y,z); d3d_draw_model(modelo,0,0,0,textura); d3d_transform_set_identity(); Explicando linha por linha: d3d_transform_set_identity(); identifica o que vai ser afetado. Note que h tambm um no final do cdigo, isso quer dizer que todo que esta entre essas funes ser alterado. d3d_transform_add_translation(x,y,z) defini o ponto de origem das transformaes. Os modelos tambm sero desenhados a partir dele ( como se fossem os novos pontos x, y e z do objeto).
d3d_draw_model(modelo,0,0,0,textura) desenha o modelo. Note que os pontos x,y,z so definidos como 0. Por que? A resposta simples. Quanto eu usei d3d_transform_add_translation(x,y,z) os argumentos x,y,z dele se tornaram os novos pontos de origem do modelo. Tudo que for desenhado entre os identificadores ser relativo a esta nova origem. Se o modelo fosse desenhado em 10,15,8: d3d_transform_add_translation(x,y,z); d3d_draw_model(modelo,10,15,8,textura); Seria o mesmo que desenh-lo na posio x+10,y+15,z+8 na room. d3d_transform_set_identity(); por ltimo outro identificador. Lembrando que tudo que estiver entre ele e o primeiro ser afetado. Uma coisa interessante que as transformaes funcionam em qualquer tipo de desenho do GM. Voc tambm pode us-las na hora de desenhar uma sprite, background ou texto!
12.2
Continuando a engine
Abra a engine que fez seguindo as outras aulas ou baixe por este link. Antes de continuar com as explicaes vamos resolver um bug nessa engine. O movimenta da cmera no esta seguindo direito o movimento do personagem. Quanto ns movimentamos o objeto a cmera puxa pros lados. Para resolver isso apague as linhas de cdigo abaixo no evento Step e coloque-os no evento Draw antes da funo de projeo no objCamera: // Calculando posio da camera no mundo x = obj1.x+dx*zoom; y = obj1.y+dy*zoom; z = obj1.z+dz*zoom; // px py pz Movimento no personagem = obj1.x; = obj1.y; = obj1.z;
O evento Step ficar assim: // Definindo angulos a partir do mouse zang-=(window_mouse_get_x()-200)/8; yang-=(window_mouse_get_y()-200)/8; window_mouse_set(200,200); yang=median(yang,-89,89); // Animao da camera
// calculando movimento dos vetores da camera dx=cos(degtorad(zang)); dy=-sin(degtorad(zang)); dz=tan(degtorad(yang)); /* normalizar vetores torna movimento da camera totalmente esferico. */ m=sqrt(sqr(dx)+sqr(dy)+sqr(dz)); dx/=m; dy/=m; dz/=m; // Zoom if keyboard_check(vk_add) zoom += 4; if keyboard_check(vk_subtract) zoom -= 4; E o evento Draw assim: // Calculando posio da camera no mundo x = obj1.x+dx*zoom; y = obj1.y+dy*zoom; z = obj1.z+dz*zoom; // px py pz Movimento no personagem = obj1.x; = obj1.y; = obj1.z;
d3d_set_projection_ext(x,y,z,px,py,pz,0,0,1,90,1.3,1,32000); Agora sim a cmera est tima. Mude o desenho do cubo para uma forma mais achatada para dar uma impresso de ser um carro. Troque os valores no cdigo que desenha o cubo no evento Draw do obj1: d3d_draw_block(-16,-32,-10,16,32,10,tex,1,1); Agora est tudo pronto para a prxima explicao.
12.3
Rotao e Escalao
As funes seguintes podem ser usadas para rotacionar e escalar os objetos: d3d_transform_add_rotation_x(angle) Gira o objeto em torno do eixo x. d3d_transform_add_rotation_y(angle) Gira o objeto em torno do eixo y. d3d_transform_add_rotation_z(angle) Gira o objeto em torno do eixo z. d3d_transform_add_scaling(xs,ys,zs) Altera a escala nos eixos x, y e z.
Vamos fazer um teste na nossa engine para entender o funcionamento. Crie variaveis rx, ry e rz no evento Create do obj1: rx = 0; ry = 0; rz = 0; Ela ser o valor do ngulo das rotaes. No evento Step adicione isso para mudar os ngulos com os nmeros do teclado numrico: if if if if if if keyboard_check(vk_numpad1) keyboard_check(vk_numpad4) keyboard_check(vk_numpad2) keyboard_check(vk_numpad5) keyboard_check(vk_numpad6) keyboard_check(vk_numpad3) rx rx ry ry rz rz += -= += -= += -= 1; 1; 1; 1; 1; 1;
No evento Draw vamos adicionar a funo de rotao dos eixos. Elas devem estar sempre antes da funo d3d_transform_add_translation. A parte que desenha o cubo ficar assim: d3d_transform_set_identity() d3d_transform_add_rotation_x(rx); d3d_transform_add_rotation_y(ry); d3d_transform_add_rotation_z(rz); d3d_transform_add_translation(x,y,z); d3d_draw_block(-16,-32,-10,16,32,10,tex,1,1); d3d_transform_set_identity() Teste o jogo e aperte 1 e 4 para girar no eixo x, 2 e 5 para girar no eixo y e 3 e 6 para girar no eixo z. Notou a diferena entre eixo x, y e z? Bom, agora hora de testar as escalas. No evento Create do obj1 adicione mais variveis para cada escala: sx = 1; sy = 1; sz = 1; E no Step o cdigo para mudar as escalar:
if if if if if if
keyboard_check(vk_delete) sx += 0.1; keyboard_check(vk_insert) sx -= 0.1; keyboard_check(vk_end) sy += 0.1; keyboard_check(vk_home) sy -= 0.1; keyboard_check(vk_pagedown) sz += 0.1; keyboard_check(vk_pageup) sz -= 0.1;
No evento Draw adicione a funo para escalar o modelo tambm sempre antes de d3d_transform_add_translation. d3d_transform_set_identity() d3d_transform_add_rotation_x(rx); d3d_transform_add_rotation_y(ry); d3d_transform_add_rotation_z(rz); d3d_transform_add_scaling(sx,sy,sz); d3d_transform_add_translation(x,y,z); d3d_draw_block(-16,-32,-10,16,32,10,tex,1,1); d3d_transform_set_identity() Teste e use Delete e Insert para mudar o eixo x, End e Home para o eixo y, Page Up e Page Down para o eixo z.
12.4
Movimentao
A movimentao dessa engine ser da seguinte forma: As teclas A e D giram o objeto, W e S acelera e desacelera, C muda o modo da cmera. Apague as novas variveis que criamos e faa apenas uma para a rotao r, y_speed para a velocidade e mude o valor z para 16. Evento Create Completo: z = 16; tex = background_get_texture(background0); tex2 = background_get_texture(background1); x = 96; y = 96; r = 0; // rotao z y_speed = 10; // velocidade Apague todo o cdigo no evento Step e coloque este para girar o carro para os lados: if keyboard_check(ord('A')) r += 2; if keyboard_check(ord('D')) r -= 2;
O carro tem que andar na direo que esta virado ento temos que usar cos e sin para achar x e y de acordo com o ngulo. No evento Step adicione este cdigo: if keyboard_check(ord('W')) { x += cos(degtorad(r+90))*y_speed; y -= sin(degtorad(r+90))*y_speed; } if keyboard_check(ord('S')) { x -= cos(degtorad(r+90))*y_speed; y += sin(degtorad(r+90))*y_speed; } O r+90 ajeita o ngulo de calculo para faze-lo correr na direo certa. Por ultimo deixe o evento Draw desta forma: d3d_transform_set_identity() d3d_transform_add_rotation_z(r); d3d_transform_add_translation(x,y,z); d3d_draw_block(-16,-32,-10,16,32,10,tex,1,1); d3d_transform_set_identity() d3d_draw_floor(0,0,0,room_width*3,room_height*3,0,tex2,10,10); Isso muda a rotao do eixo z e aumento o tamanho do cho. Teste o jogo veja o resultado! Veja a engine desse captulo, arquivo GM3D 03.gmk.
13.1
GNU GPL 3
Leia abaixo uma verso compacta da GNU GPL 3 (em ingls): GNU GENERAL PUBLIC LICENSE Version 3, 29 June 2007 TERMS AND CONDITIONS 0. Definitions. "This License" refers to version 3 of the GNU General Public License. "Copyright" also means copyright-like laws that apply to other kinds of works, such as semiconductor masks. "The Program" refers to any copyrightable work licensed under this License. Each licensee is addressed as "you". "Licensees" and "recipients" may be individuals or organizations. To "modify" a work means to copy from or adapt all or part of the work in a fashion requiring copyright permission, other than the making of an exact copy. The resulting work is called a "modified version" of the earlier work or a work "based on" the earlier work. A "covered work" means either the unmodified Program or a work based on the Program. To "propagate" a work means to do anything with it that, without permission, would make you directly or secondarily liable for infringement under applicable copyright law, except executing it on a computer or modifying a private copy. Propagation includes copying, distribution (with or without modification), making available to the public, and in some countries other activities as well. To "convey" a work means any kind of propagation that enables other parties to make or receive copies. Mere interaction with a user through a computer network, with no transfer of a copy, is not conveying. 1. Basic Permissions. All rights granted under this License are granted for the term of copyright on the Program, and are irrevocable provided the
stated conditions are met. This License explicitly affirms your unlimited permission to run the unmodified Program. The output from running a covered work is covered by this License only if the output, given its content, constitutes a covered work. This License acknowledges your rights of fair use or other equivalent, as provided by copyright law. You may make, run and propagate covered works that you do not convey, without conditions so long as your license otherwise remains in force. You may convey covered works to others for the sole purpose of having them make modifications exclusively for you, or provide you with facilities for running those works, provided that you comply with the terms of this License in conveying all material for which you do not control copyright. Those thus making or running the covered works for you must do so exclusively on your behalf, under your direction and control, on terms that prohibit them from making any copies of your copyrighted material outside their relationship with you. Conveying under any other circumstances is permitted solely under the conditions stated below. Sublicensing is not allowed; section 10 makes it unnecessary. 2. Termination. You may not propagate or modify a covered work except as expressly provided under this License. Any attempt otherwise to propagate or modify it is void, and will automatically terminate your rights under this License (including any patent licenses granted under the third paragraph of section 11). However, if you cease all violation of this License, then your license from a particular copyright holder is reinstated (a) provisionally, unless and until the copyright holder explicitly and finally terminates your license, and (b) permanently, if the copyright holder fails to notify you of the violation by some reasonable means prior to 60 days after the cessation. Moreover, your license from a particular copyright holder is reinstated permanently if the copyright holder notifies you of the violation by some reasonable means, this is the first time you have received notice of violation of this License (for any work) from that copyright holder, and you cure the violation prior to 30 days after your receipt of the notice. Termination of your rights under this section does not terminate the licenses of parties who have received copies or rights from you under this License. If your rights have been terminated and not permanently reinstated, you do not qualify to receive new licenses for the same material under section 10. 3. No Surrender of Others' Freedom. If conditions are imposed on you (whether by court order, agreement or otherwise) that contradict the conditions of this License, they do not excuse you from the conditions of this
License. If you cannot convey a covered work so as to satisfy simultaneously your obligations under this License and any other pertinent obligations, then as a consequence you may not convey it at all. For example, if you agree to terms that obligate you to collect a royalty for further conveying from those to whom you convey the Program, the only way you could satisfy both those terms and this License would be to refrain entirely from conveying the Program. 15. Disclaimer of Warranty. THERE IS NO WARRANTY FOR THE PROGRAM, TO THE EXTENT PERMITTED BY APPLICABLE LAW. EXCEPT WHEN OTHERWISE STATED IN WRITING THE COPYRIGHT HOLDERS AND/OR OTHER PARTIES PROVIDE THE PROGRAM "AS IS" WITHOUT WARRANTY OF ANY KIND, EITHER EXPRESSED OR IMPLIED, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE. THE ENTIRE RISK AS TO THE QUALITY AND PERFORMANCE OF THE PROGRAM IS WITH YOU. SHOULD THE PROGRAM PROVE DEFECTIVE, YOU ASSUME THE COST OF ALL NECESSARY SERVICING, REPAIR OR CORRECTION. 16. Limitation of Liability. IN NO EVENT UNLESS REQUIRED BY APPLICABLE LAW OR AGREED TO IN WRITING WILL ANY COPYRIGHT HOLDER, OR ANY OTHER PARTY WHO MODIFIES AND/OR CONVEYS THE PROGRAM AS PERMITTED ABOVE, BE LIABLE TO YOU FOR DAMAGES, INCLUDING ANY GENERAL, SPECIAL, INCIDENTAL OR CONSEQUENTIAL DAMAGES ARISING OUT OF THE USE OR INABILITY TO USE THE PROGRAM (INCLUDING BUT NOT LIMITED TO LOSS OF DATA OR DATA BEING RENDERED INACCURATE OR LOSSES SUSTAINED BY YOU OR THIRD PARTIES OR A FAILURE OF THE PROGRAM TO OPERATE WITH ANY OTHER PROGRAMS), EVEN IF SUCH HOLDER OR OTHER PARTY HAS BEEN ADVISED OF THE POSSIBILITY OF SUCH DAMAGES. A verso completa da GNU GPL 3 se encontra no arquivo licena GLP.txt.