Documente Academic
Documente Profesional
Documente Cultură
GAME MAKER
Verso 1.0
ESCRITORES
fUzEnRaD
Idealizador e editor
ndice
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
10. GM3D - Primeiros passos I. O que pode ser feito em 3D no Game Maker II. A terceira dimenso! III. Construindo uma Engine 11. GM3D Projeo e Movimento da Cmera I. A funo d3d_set_projection_ext II. A funo d3d_set_projection_ortho III. Movimentando a cmera 12. GM3D Usando Transformaes I. Transformaes II. Continuando a engine III. Rotao e Escalao IV. Movimentao 13. Licena de uso, modificao e distribuio I. GNU GPL 3
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.
Crie um objeto. Chame-o de "pers_1". Crie o evento Other > Game Start. Agora digite o seguinte cdigo: global.pers = 0;
Esse cdigo ir setar a opo "defalt". ( tipo o que est selecionado antes do usurio escolher) Agora crie outro evento. O evento Mouse > Left Button. Digite o mesmo cdigo citado acima. Isso ir alterar o personagem selecionado para ele, se o outro estiver selecionado. No mesmo evento, digite mais um cdigo: room_goto_next()
Crie outro objeto, e nomeie-o como "pers_2". Coloque o evento Mouse > Left Button, coloque o seguinte cdigo: global.pers = 1;
Isso ir alterar o personagem selecionado para ele, se o outro estiver selecionado. room_goto_next()
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_point(x1,y1) draw_rectangle(x1,y1,x2,y2,linha) draw_triangle(x1,y1,x2,y2,x3,y3,linha) draw_circle(x1,y1,raio,linha) //Entre outros
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 c_teal //Azul
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*/
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) draw_rectangle(10,10,110,110,1) draw_rectangle(24,48,84,108,1)
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 draw_rectangle_color(0,0,150,150,c_red,c_white,c_green,c_purple,0) //Exemplo 2 draw_rectangle_color(0,0,150,150,c_red,c_white,c_green,c_purple,1)
Exemplo 1
Exemplo 2
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 draw_set_circle_precision(10) draw_circle(100,100,10,0) //Exemplo 2 draw_set_circle_precision(100) draw_circle(100,100,10,0)
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: for (pos=1; pos<=10; pos+=1) { draw_text(x,y+pos*20,string(pos)+". "+highscore_name(pos))}
Comentando:
for (pos=1; pos<=10; pos+=1) { draw_text(x,y+pos*20,string(pos)+". "+highscore_name(pos))}
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) }
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.
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:
Define qual a velocidade mxima que o carro poder atingir. aceleracao = 0.2
Define a acelerao do carro, quanto maior, menos tempo levar para alcanar a velocidade mxima. freio = 0.2
Define a fora do freio do carro, quanto maior, menos tempo ele levar para atingir 0 quando estiver freiando. curva = 2.5
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: //Musica e efeitos sonoros sound_add() sound_replace() sound_delete()
//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.
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: " + string(exper_atual)+ "/" + string(exper_max),c_white,c_silver,c_white,c_ltgray,image_alpha) //As informaes do personagem
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:
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.*/
E no evento Draw quase a mesma coisa do objeto boto: 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
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.
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.
O draw do objeto boto Cancelar: if image_single=0 draw_text_color(jan_mplayer.x+208,jan_mplayer.x+107,"Cancelar", c_black,c_dkgray,c_black,c_black,image_alpha) else draw_text_color(jan_mplayer.x+208,jan_mplayer.x+107,"Cancelar", c_red,c_red,c_black,c_red,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.
Para permitir a edio de um texto, eu criei o seguinte cdigo: 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_a lpha) 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.
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.
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.
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: x=room_width/2 y=room_height/2 mostra=0
Centraliza o objeto na room e inicia a varivel mostra. No evento Step: 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.
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.
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);
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;
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.
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,an gle,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.
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.
Abra o obj1 e defina outra varivel para a textura do cho: tex2 = background_get_texture(background1);
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
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!
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);
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;
if if if if if
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.
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.