[Tutorial] Surfaces

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

Qualidade [Tutorial] Surfaces

Mensagem por saim em Seg 06 Jun 2011, 15:15

Nome: Dicas a respeito de surfaces
Descrição: Aqui, vamos discutir como usar surfaces
Nível de dificuldade: Não sei. Me ajudem aí, nos comentários. Acho que é intermediário, mas tem coisas bem básicas.
Requerimentos: GM Pro, exemplos feitos com a versão 8


surfaces: Que bicho de 7 cabeças é esse tal de surfaces? Bicho nenhum. Surface é uma tela, só isso. Pense num paint brush, só que, ao invés de desenhar com o mouse, você vai desenhar com o teclado.
Você cria uma surface usando a função "surface_create(largura, altura)". Pronto, você criou uma surface. Ah, essa função te retorna a id da surface pra você usar depois, em outras funções, portanto armazene essa id numa variável. Vou chamar ela de "Surf", com "S" maiúsculo pro GM não sugerir autocompletar.
Código:
"Surf=surface_create(largura, altura)".
Uma tela serve pra desenhar. Só que o GM, por padrão, desenha na tela que é mostrada durante o jogo (sim, ela também é uma surface, mas é outra história). Pra desenhar na SUA surface, você deve explicar ao GM o que você quer. A função que estou falando é "surface_set_target(id)". No nosso caso, a variável que armazenou a id da surface é "Surf", ou seja:
Código:
surface_set_target(Surf)
Sabe o que tem nela, quando ela criada? Eu também não. Uma vez mandei desenhar uma surface que tinha acabado de ser criada, sem colocar nada nela e o que eu vi, não foi bonito. Portanto, vamos garantir que ela seja uma tela totalmente lisa, antes de começar a trabalhar. Tem as funções "draw_clear(cor)" e "draw_clear_alpha(cor, opacidade)". Eu gosto de usar draw_clear_alpha(0,0). Essas funções servem pra limpar a surface de cima abaixo (e elas podem ser usadas na tela do jogo, também). Porque eu usei a cor "0"? Resposta no tutorial de cores (num futuro perto da sua casa!).
Ok, criamos, definimos que é nela que vamos desenhar e pintamos ela toda de preto. E agora? Agora, desenhe pra valer. Todas as funções de draw funcionam na surface, esteja você no evento em que estiver (sim, você pode desenhar fora do draw event).
Vai lá, desenha. Você pode desenhar sprites, linhas, triângulos (dá pra fazer qualquer coisa com um número suficiente de triângulos), círculos, outras surfaces, a própria surface, pode desenhar a tela, pode fazer o que quiser, desde que com código. Se você for bom de serviço, dá até pra usar uma interface com o usuário pra desenhar, mas isso foge do nosso assunto.
Desenhou pra valer? Ótimo. Agora chega. Depois você vai ao banheiro, estamos quase acabando, aqui.
Agora precisamos guardar essa tela. Em outras palavras, parar de desenhar na sua surface e voltar a desenhar na surface built-in que é a própria tela do jogo.
Código:
surface_reset_target()
Quer VER sua surface? Vá no draw_event e coloque:
Código:
draw_surface(Surf, x, y)
Fim.

...

"Só isso?"
Bom, eu achei que já tava bom, mas já que é assim, vamos extender um pouco mais. Você está pensando "por que fazer a surface se eu posso fazer isso tudo direto na tela?", não é mesmo? Ok, deixa eu dar alguns exemplos do que se pode fazer com surfaces.

pausa - Quando você desativa todas as intâncias (instance_deactivate_all(1)), desativa todos os eventos delas, inclusive o evento de draw. Isso faz elas sumirem. Como fazer uma pausa que mostre a tela parada, sem ter que alterar o código de um-por-um dos objetos? Desative as instâncias mesmo mas, antes disso, crie uma surface com o evento de draw de todas elas. pra chamar o evento de draw de todas elas, não precisa usar with(all){event_perform(ev_draw, 0)}. Tem uma função ótima pra isso, "screen_redraw()". Crie a surface, desenhe tudo com screen_redraw(), desative todas as instâncias, desenhe a surface no draw event. Não, sério, é simples mesmo, olha só, coloque isso no obj_pausa:
evento de pausar
Código:
if !pausa{
   Surf=surface_create(room_width, room_height)
   surface_set_target(Surf)
   screen_redraw()
   surface_reset_target()
   instance_desctivte_all(1)
   }
   else{
   instance_activate_all
   surface_free(Surf)  //apaga a surface, liberando memória
   }
e, no draw event,
Código:
if pausa
   draw_surface(Surf, 0, 0)

personalização de sprites - Suponha que você esteja criando um RPG e queira que ao usar um capacete, por exemplo, o desenho do personagem mude pra um personagem com capacete. Primeiro você cria us sprites do personagem andando pra todo lado e outros do capacete, na altura da cabeça do personagem, andando pros mesmos lados, certo? Certo. Aí, no draw event, você coloca a imagem adequada do personagem e, por cima, a imagem adequada do capacete, certo? ERRADO. Na hora de adquirir o capacete, você cria toda uma série de sprites do personagem COM o capacete e desenha os novos sprites. É simples, olha:
Código:
var i, Surf, xop, yop, xoc, yoc;
//armazena a origem dos sprites
xop=sprite_get_xoffset(spr_personagem)
yop=sprite_get_yoffset(spr_personagem)
xoc=sprite_get_xoffset(spr_capacete)
yoc=sprite_get_yoffset(spr_capacete)
Surf=surface_create(largura, altura)//largura e altura do sprite final
for(i=0; i<numero_de_imagens; i+=1){
   draw_clear_alpha(0, 0)                  //aqui, você realmente quer eliminar o fundo
   draw_sprite(spr_personagem, i, xop, yop) //desenha o personagem, sem nada
   draw_sprite(spr_capacete,  i, xoc, yoc) //desenha o capacete, por cima
   if i=0{                                  //só pro primeiro índice
      spr_vestido=sprite_create_from_surface(Surf, 0, 0, largura, altura, 0, 0, xop, yop,) //cria o sprite
      }
      else{ //se não é o primeiro índice, o sprite já existe
         sprite_add_from_surface(spr_vestido, Surf, 0, 0, largura, altura, 0, 0) //só adicionar a imagem
         }
   }
surface_reset_target()//desliga a surface
surface_free(Surf)    //não preciso mais da surface, elimino-a pra economizar memória.
Muita coisa pra um evento só? Talvez. Mas isso vai economizar processamento durante o jogo, que é quando realmente importa. Sim, isso é simples! É só um amontoado de linhas, mas fácil de entender.

screenshots - Quer publicar seu jogo e precisa de uma screenshot? Fácil! Em algum evento, crie uma surface do tamanho da room, desenhe a room e grave essa surface num arquivo de imagem! Olha só:
Código:
var Surf;
Surf=surface_create(room_width, room_height)
surface_set_target(Surf)
draw_clear_alpha(0, 0)
screen_redraw()
surface_reset_target()
surface_save(Surf, "screenshot.png") //GM8
surface_free(Surf)

efeitos especiais - Bom, isso é mais complicado e eu não sei criar um exemplo, mas sabe aqueles efeitos que distorcem a tela toda e/ou parte dela, tipo uma lente de aumento... Ah, uma lente de aumento eu sei criar! Você desenha a tela toda numa surface e, em outra menor, desenha essa primeira surface, mas deslocada, de modo que a parte a ser aumentada encaixe direitinho na janela menor. Elimine a primeira e, no draw event, desenhe draw_surface_stretched. Pra conseguir uma lente circular, recorte, na surface menor, a parte que sobrar. "Ah, tá, e pra recortar, como faz?" Cara, isso é simples, só que é complicado. Fica pro tutorial de blend modes, num futuro um pouco mais distante que o de cores. Resumindo, você cria uma surface "faca" desenhando um quadrado todo branco e subtraindo (bm_subtract) um círculo branco dele. Depois, você subtrai essa surface toda-branca-com-buraco-redondo da surface-lupa, deixando só o que estiver no buraco e voilá. Imagine o que dá pra fazer com primitives e textures!
(na verdade, pode haver um problema em desenhar, no draw_event, uma surface que é criada usando screen_draw, porque você vai desenhar a própria surface. Mas isso não gera nenhum buraco no universo, só uma surface estranha).

Bom, é isso! Se eu não fui claro em algum aspecto ou exemplo, me avisem.
Abraço! Te vejo no tutorial de cores!

Edit: Lembra que eu falei que não é uma boa idéia desenhar a tela numa surface que será desenhada na mesma tela? Mantenho o que disse, mas fiquei com consciência pesada. Que tutorial é esse que fala do problema e não resolve?
Bom, acho que não preciso explicar porque não é uma boa idéia fazer isso. Isso é uma má idéia porque a própria surface vai ser desenhada sobre ela mesma e, quando você faz isso, normalmente que fazer uma distorção na imagem, então essa distorção acaba sendo aumentada exponencialmente.
Mas o que fazer, então? Não sei. Sério, não sei mesmo. Mas tem um truque que pode ser interessante.
Tem outra coisa que já falei que pode ser uma boa dar uma relembrada. A tela que é mostrada durante o jogo também é uma surface. Você não precisa mandar desenhar nela porque o game maker está programado pra fazer isso. Mas você pode mandar parar de fazer. A função pra isso é
Código:
set_automatic_draw(false)
Isso faz a tela parar de ser desenhada.
Calma, não quer dizer que o jogo vai ficar sem imagem nenhuma. Quer dizer que, ao chegar no final do draw_event, o programa vai parar de desenhar a surface da tela por cima de tudo o que já tiver sido desenhado. Ou seja, vai passar a ser possível desenhar em qualquer evento. Como o screen_redraw só executa os eventos de draw e você NÃO vai desenhar essa surface no draw, ela não vai ser re-desenhada. Claro que isso pode gerar uma série de problemas (que eu não consigo imaginar agora), mas se for usado com cuidado, pode ficar bacana.
Olha como ficaria uma lupa:
create:
Código:
//primeiro, faz a faca
faca=surface_create(50, 50)      //os valores, você altera a gosto
surface_set_target(faca)        //passa a desenhar na surface
draw_clear_alpha(c_white, 1)    //deixa a surface toda branca
draw_set_blend_mode(bm_subtract) //passa a apagar, ao invés de desenhar
draw_circle_color(25, 25, 25, $ffffff, $ffffff, 0) //apaga um círculo no centro da surface
draw_set_blend_mode(bm_normal)  //volta o blend_mode ao normal
surface_reset_target()          //larga a surface quieta
step:
Código:
if mouse_check_button(mb_left){ //se o mouse está pressionado
   set_automatic_draw(false) //para de redesenhar a tela
   var Surf;                //cria uma variável pra redesenhar tela
   Surf=surface_create(room_width, room_height) //cria a surface que redesenhará a tela
   surface_set_target(Surf)  //passa a desenhar na surface
   draw_clear_alpha(0, 0)    //apaga tudo
   screen_redraw()          //desenha tudo
   surface_reset_target()    //para de desenhar na surface
   
   lupa=surface_create(50, 50)      //tem que ser do tamanho da faca
   surface_set_target(lupa)        //passa a desenhar na surface
   draw_surface(Surf, -mouse_x, -mouse_y) //desenha a outra surface, adequadamenteposicionada
   draw_set_blend_mode(bm_subtract) //passa a apagar ao invés de desenhar
   draw_surface(sf_faca, 0, 0)      //recorta, usando a faca
   draw_set_blend_mode(bm_normal)  //volta a desenhar ao invés de apagar
   surface_reset_target()          //para de desenhar na surface
   
   draw_surface(Surf, 0, 0)                                //desenha a surface com a tela
   draw_surface_stretched(lupa, mouse_x, mouse_y, 100, 100) //desenha a surface com a lupa, esticada
   
   surface_free(Surf) //elimina a surface da tela
   }else //se o mouse está solte
      set_automatic_draw(true) //mantém a tela sendo desenhada normalmente
Gente, MUITO JUÍZO ao fazer isso. Supondo que o objeto possa ser deletado em algum momento, lembre-se sempre de colocar o blend_mode de volta ao normal e o set_automatic_draw de volta a true no destroy event.


Última edição por saim em Qua 29 Jun 2011, 15:49, editado 3 vez(es)

saim

Ranking : Nota B
Número de Mensagens : 2964
Idade : 38
Data de inscrição : 14/01/2011
Notas recebidas : C-D-A-B
Reputação : 121
Insignia 1 x 0 Insignia 2 x 0 Insignia 3 x 0
Prêmios
   : 1
   : 0
   : 3

Voltar ao Topo Ir em baixo

Qualidade Re: [Tutorial] Surfaces

Mensagem por Lucas 5293 em Seg 06 Jun 2011, 17:47

Otimo tutorial
eu não sabia o que era surface agora sei

Lucas 5293

Ranking : Nota C
Número de Mensagens : 695
Idade : 18
Data de inscrição : 10/12/2010
Notas recebidas : C-D-B-B-B-C-C-C
Reputação : 18
Insignia 1 x 0 Insignia 2 x 0 Insignia 3 x 0
Prêmios
   : 0
   : 1
   : 0

http://dopxgames.blogspot.com

Voltar ao Topo Ir em baixo

Qualidade Re: [Tutorial] Surfaces

Mensagem por saim em Ter 07 Jun 2011, 13:00

Que bom que ajudou alguém! Eu vou me referir a ele no meu próximo tutorial (se eu conseguir completar ele), de cores. Quando comeceia usar surfaces, me pareceu meio inútil, hoje acabo usando elas pra quase todos os jogos.
Usando surfaces, blend modes e uns truques de salão, dá pra fazer muitos efeitos legais a partir de poucos (ou nenhum) sprites.

saim

Ranking : Nota B
Número de Mensagens : 2964
Idade : 38
Data de inscrição : 14/01/2011
Notas recebidas : C-D-A-B
Reputação : 121
Insignia 1 x 0 Insignia 2 x 0 Insignia 3 x 0
Prêmios
   : 1
   : 0
   : 3

Voltar ao Topo Ir em baixo

Qualidade Re: [Tutorial] Surfaces

Mensagem por fredcobain em Qua 08 Jun 2011, 00:03

Amigo, eu nunca me atentei pra real utilidade das surfaces.... vou fazer alguns testes com base no seu tutorial (excelente como de costume).

Parabéns e obrigado!

=)

fredcobain

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

Voltar ao Topo Ir em baixo

Qualidade Re: [Tutorial] Surfaces

Mensagem por MatheusReis em Qua 08 Jun 2011, 09:20

Muito bom... mas a minha dúvida AINDA é sobre "cortar" a surface na forma que eu quero scratch (ao exemplo da lente de aumento)
Bem... fica para a próxima.
Seria possível, quando tiver tempo, um tutorial mais avançado de surfaces? Ou um update nesse explicando mais funções?
(Por que, já sabe, surface tem um bucado de comandos =D).

MatheusReis

Ranking : Nota A
Número de Mensagens : 1087
Idade : 23
Data de inscrição : 13/01/2010
Notas recebidas : B-A-A
Reputação : 30
Insignia 1 x 0 Insignia 2 x 0 Insignia 3 x 0
Prêmios
   : 2
   : 1
   : 0

http://www.mathaeuz.deviantart.com

Voltar ao Topo Ir em baixo

Qualidade Re: [Tutorial] Surfaces

Mensagem por saim em Qua 08 Jun 2011, 10:23

fredcobain escreveu:Amigo, eu nunca me atentei pra real utilidade das surfaces.... vou fazer alguns testes com base no seu tutorial (excelente como de costume).

Parabéns e obrigado!

=)
Valeu, Fred!

Mathaeuz escreveu:Muito bom... mas a minha dúvida AINDA é sobre "cortar" a surface na forma que eu quero scratch (ao exemplo da lente de aumento)
Bem... fica para a próxima.
O lance é que, pra cortar, o truque não é o uso de surfaces, mas de blend modes, por isso não me aprofundei. Um truque rápido seria fazer a "faca" em branco e alpha=1, ir para o bm_subtract e desenhar a faca, ou seja, subtrair da surface tudo o que estiver em branco. Lembre-se de voltar pro bm_normal, depois. Nunca deixei de voltar, pra testar o que acontece, mas sei que não seria bonito.
Mathaeuz escreveu:Seria possível, quando tiver tempo, um tutorial mais avançado de surfaces? Ou um update nesse explicando mais funções?
(Por que, já sabe, surface tem um bucado de comandos =D).
Tem um pouco mais de comandos do que esses que eu mostrei, mas poucos que merecem um tutorial. No máximo, uma tradução do manual, mas já existe um tópico com essa tradução. Estou falando daquelas "surface_exists", "draw_surface_general", coisa do tipo. Se houver mais alguma família de funções que fuja disso, por favor me avise pra eu estudar e incluir no tuto.

Existem mais dois tutoriais previstos que usam esse aqui como base: o de cores e o de blending. O de cores está quase pronto. O de blending seria uma tradução de outro tutorial que li na internet. Acho que você vai gostar do de blending. Se você sabe inglês, já pode ler ele aqui.

saim

Ranking : Nota B
Número de Mensagens : 2964
Idade : 38
Data de inscrição : 14/01/2011
Notas recebidas : C-D-A-B
Reputação : 121
Insignia 1 x 0 Insignia 2 x 0 Insignia 3 x 0
Prêmios
   : 1
   : 0
   : 3

Voltar ao Topo Ir em baixo

Qualidade Re: [Tutorial] Surfaces

Mensagem por GameMakerTutoriais em Qua 15 Jun 2011, 10:31

Bom tutorial. O melhor sobre surface do fórum Very Happy

Esse lance de copiar a surface principal com screen_redraw() dentro de outra surface eu descobri por acaso uma vez... bem mais rápido que "screen_save()" pelo menos umas 40 vezes...

Legal, parabéns belo tutorial!

GameMakerTutoriais

Número de Mensagens : 800
Data de inscrição : 29/01/2011
Reputação : 26
Insignia 1 x 0 Insignia 2 x 0 Insignia 3 x 0
Prêmios
   : 0
   : 0
   : 0

Voltar ao Topo Ir em baixo

Qualidade Re: [Tutorial] Surfaces

Mensagem por Mr.Brum em Ter 12 Jul 2011, 10:12

Muito Bom o tutorial... Parabéns!!
Tá ajudando pakas...!

Mr.Brum

Ranking : Nota C
Número de Mensagens : 913
Idade : 25
Data de inscrição : 28/04/2011
Notas recebidas : D + D + C + C + D + B
Reputação : 41
Insignia 1 x 0 Insignia 2 x 0 Insignia 3 x 0
Prêmios
   : 1
   : 0
   : 0

http://mrbrumgames.blogspot.com/

Voltar ao Topo Ir em baixo

Qualidade Re: [Tutorial] Surfaces

Mensagem por Luiz A. Oliveira em Ter 12 Jul 2011, 11:12

Muito bom tutorial, adoro usar Surfaces (fazendo efeitos visuais). Se eu tiver alguma dúvida ja sei pra quem perguntar!!!

Té mais.

Luiz A. Oliveira

Ranking : Nota C
Número de Mensagens : 914
Idade : 19
Data de inscrição : 08/09/2010
Notas recebidas : D-B-C
Reputação : 5
Insignia 1 x 0 Insignia 2 x 0 Insignia 3 x 0
Prêmios
   : 0
   : 0
   : 0

http://luizgm.blogspot.com/

Voltar ao Topo Ir em baixo

Qualidade Re: [Tutorial] Surfaces

Mensagem por Conteúdo patrocinado Hoje à(s) 12:30


Conteúdo patrocinado


Voltar ao Topo Ir em baixo

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

- Tópicos similares

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