Baixe o app para aproveitar ainda mais
Prévia do material em texto
PROGRAMAÇÃO DE SOFTWARE BÁSICO EM C ARA0363 Prof: Maximiano Correia Martins, D.Sc Aula 3 INICIAREMOS EM INSTANTES Plano de Aula: 3ª Aula de Programação de software básico • Compreender o uso da biblioteca OpenGL em C. • Desenvolver programas com interface e recursos visuais. • Aprender os conceitos de animação de objetos gráficos. • Compreender o uso da biblioteca OpenGL para captura de eventos de teclado e mouse. • Desenvolver programas em C com captura de eventos. • Aprender os conceitos de animação de objetos gráficos. • Compreender os antigos acessos a registros com o DOS. API OpenGL O uso de APIs mais elaboradas é um desafio, pois em geral exigem a consulta da documentação da mesma e a busca por exemplos já desenvolvidos para que possamos chegar a uma compreensão de como executar o que necessitamos. Um bom exemplo é a API OpenGL, que veremos nesta aula. OpenGL, abreviação de "Open Graphics Library", é uma interface de programação de aplicativos (API) projetada para renderizar gráficos 2D e 3D. Ele fornece um conjunto comum de comandos que podem ser usados para gerenciar gráficos em diferentes aplicativos e em várias plataformas. Usando o OpenGL Ao usar o OpenGL, um desenvolvedor pode usar o mesmo código para renderizar gráficos em um Mac, PC ou dispositivo móvel. Quase todos os sistemas operacionais e dispositivos de hardware modernos oferecem suporte ao OpenGL, tornando-o uma escolha fácil para o desenvolvimento de gráficos. Além disso, muitas placas de vídeo e GPUs integradas são otimizadas para o OpenGL, permitindo que eles processem comandos do OpenGL com mais eficiência do que outras bibliotecas gráficas. Usando o OpenGL Exemplos de comandos do OpenGL incluem desenhar polígonos, atribuir cores a formas, aplicar texturas a polígonos (mapeamento de textura), aumentar e diminuir o zoom, transformar polígonos e girar objetos. O OpenGL também é usado para gerenciar efeitos de iluminação, como fontes de luz, sombreamento e sombras. Também pode criar efeitos como neblina ou neblina, que podem ser aplicados a um único objeto ou a uma cena inteira. Usando o OpenGL O OpenGL é comumente associado a videogames por causa de seu amplo uso em jogos 3D. Ele fornece aos desenvolvedores uma maneira fácil de criar jogos de plataforma cruzada ou portar um jogo de uma plataforma para outra. O OpenGL também é usado como biblioteca de gráficos para muitos aplicativos CAD, como AutoCAD e Blender. Até a Apple usa o OpenGL como base das bibliotecas de gráficos macOS Core Animation, Core Image e Quartz Extreme. OpenGL Histórico O OpenGL foi originalmente desenvolvido e lançado pela Silicon Graphics (SGI) em 1992. A versão inicial foi aprovada por um conselho de revisão de arquitetura, que incluía Microsoft, IBM, DEC e Intel. Em 2006, a SGI transferiu o desenvolvimento e a manutenção do OpenGL para o The Khronos Group. Antes do OpenGL e de outras APIs gráficas, como a DirectX, os jogos tinham que usar instruções especiais, dependendo da placa gráfica que se possuía. Ao comprar um novo jogo, você tinha que verificar cuidadosamente se o seu cartão era suportado. Como funciona a comunicação CPU X Monitor de Vídeo A CPU (que é onde o programa que você escreve é executado) não pode falar diretamente com a tela ou monitor. Em vez disso, você envia os dados que deseja desenhar para a GPU (Graphics Processing Unit, ou Unidade de Processamento Gráfico). A GPU desenha os dados. APIs gráficas, como OpenGL, permitem que programas em execução na CPU enviem dados para a GPU e personalizem como esta os desenha. Portabilidade entre sistemas Embora a API OpenGL seja uma biblioteca poderosa e versátil, com cerca de 250 funções, funcionando em muitas plataformas diferentes para a construção de ambientes, os princípios de programação seguem o de qualquer outra biblioteca em C. As tarefas ligadas ao sistema operacional não são tratadas pela OpenGL, o que inclui funções para arquivos e janelas, sendo esta uma característica importante para a portabilidade entre sistemas. Dada a ampla adoção do OpenGL em todos os tipos de sistemas, como Linux e Windows, além de iOS e Android, este não é mais considerado uma única API. O OpenGL evoluiu em uma família de APIs, também com aplicações em sistemas móveis e web, permitindo que os desenvolvedores de aplicativos escrevam e implantem aplicativos gráficos em uma ampla variedade de plataformas e sistemas operacionais. Instalação do OPENGL https://sourceforge.net/projects/orwelldevcpp/ Primeiro fazer o download do Dev C++ através do Link: Após o download do Dev C++, execute o programa de Instalação https://sourceforge.net/projects/orwelldevcpp/ Instalação e Configuração da Open GL Agora é só baixar a biblioteca gráfica OpenGL, uma boa solução é freeglut. http://freeglut.sourceforge.net/ http://freeglut.sourceforge.net/ Instalação e Configuração da Open GL • Após o download da OpenGL (freeglut), descompacte o arquivo • Meus Documentos\Projetos OpenGL\Bibliotecas freeglut. • Acesse a pasta free glut para ter acesso aos arquivos necessários para a configuração da OpenGL. Instalação e Configuração da Open GL • Acesse a pasta Meus Documentos\Projetos OpenGL\Bibliotecas freeglut\include\GL, e selecione todos os arquivos copiando os para C:\\Arquivos de Programas (x86)\Dev-CPP\MinGW64\x86_64-w64-mingw32\Include\GL • Acesse a pasta Meus Documentos\Projetos OpenGL\Bibliotecas freeglut\lib\x64, e selecione todos os arquivos copiando os para C:\\ArquivosdeProgramas(x86)\Dev-CPP\MinGW64\x86_64-w64-mingw32\lib • Acesse a pasta Meus Documentos\Projetos OpenGL\Bibliotecas freeglut\bin\x64 , e selecione todos os arquivos copiando os para C:\\Windows\System32 Preparando para começar a usar Para testar, criar um projeto no Dev C++ com as opções Console Application e C Project. Acrescentar em Projeto -> Opções do Projeto, na aba Parâmetros, na coluna Linkers, as seguintes instruções (figura 3): -lopengl32 -lfreeglut -lglu32 Tudo Pronto agora é só diversão!!!! OU TUTORIAL DE INSTALAÇÃO DO OPENGL Exemplos para testar: http://myhsts.org/blog/CG_Examples.html https://www.youtube.com/watch?v=8Qkpaewj-7Y http://myhsts.org/blog/CG_Examples.html https://www.youtube.com/watch?v=8Qkpaewj-7Y Primeiro Programa OPENGL ( “OLA MUNDO”) Aparecerá uma janela com fundo preto e um quadrado branco e título “Ola Mundo” na janela: Funções da GLUT principais utilizada glutInitDisplayMode(GLUT_SINGLE | GLUT_RGB) - Modo de exibição inicial usado ao criar janelas, sub-janelas e sobreposições de nível superior para determinar o modo de exibição do OpenGL para a janela ou sobreposição a ser criada. glutDisplayFunc(display) – Chama a função para redesenhar a janela. glutMainLoop() – Inicia a máquina de estados do programa gráfico. glutCreateWindow - cria uma janela de nível superior. O nome será fornecido ao sistema de janelas como o nome da janela. A intenção é que o sistema de janelas rotule a janela com o nome. Implicitamente, a janela atual é definida como a janela recém-criada. Cada janela criada possui um contexto OpenGL associado exclusivo. Alterações de estado no contexto OpenGL associado a uma janela podem ser feitas imediatamente após a criação desta. Biblioteca glut.h Os arquivos de cabeçalho para GLUT devem ser incluídos nos programas GLUT com a seguinte diretiva de inclusão: #include <glut.h> ou #include <windows.h> #include <GL/glut.h> Desenhando elementos gráficos com OpenGL http://myhsts.org/blog/CG_Examples.html http://myhsts.org/blog/CG_Examples.html As novas funções usadas do GLUT glutInitWindowSize(500,350): Esta função é utilizada para definir o tamanho em, pixels, da janela. glutInitWindowPosition(50,30): Função usada para definir a localização da janela, a posição a 50 pixels do topo e a 30 pixels da esquerda da janela do Windows. glutReshapeFunc(MudaTamanhoJanela): Define a função para mudar o tamanho da janela. A função "MudaTamanhoJanela" é chamada para recomeçaro sistema de coordenadas da janela. glColor3f(1.0f, 0.0f, 0.0f): Estabelece a cor usada para realizar o desenho. glBegin(GL_QUADS); até glEnd(): Neste conjunto de comandos realiza-se o desenho de um quadrado. A API OpenGL verifica as coordenadas, alterando para a posição atual na função já vista, a “MudaTamanhoJanela”. glViewport A chamada de função que mais se destaca é o glViewport. Uma viewport define a área desenhada pelo OpenGL; qualquer ponto que fique fora da janela de visualização não é desenhado. A razão pela qual isso é chamado da viewport é porque é uma janela para a cena, olhando apenas uma pequena área de uma cena possivelmente muito maior. É importante notificar a OpenGL sobre quaisquer alterações na janela de visualização para não desenhar pixels fora da tela, resultando em cálculos desperdiçados que seriam mais bem gastos em outros lugares. A função glViewport usa quatro parâmetros, a saber: Coordenada X Coordenada Y Largura Altura viewport As coordenadas X e Y correspondem ao canto inferior esquerdo da janela de visualização, no nosso caso, o canto inferior esquerdo da janela (0, 0). Essa função também permite que você desenhe para uma área muito específica na janela que contém, menor que a própria janela. Por exemplo, isso pode ser útil se você precisar incorporar gráficos OpenGL em uma interface do usuário. A viewport é especificada com a utilização das funções descritas abaixo glViewport(0, 0, w, h): Esta função é utilizada para armazenar os parâmetros de largura e altura da janela para que esta seja redimensionada. gluOrtho2D (0.0f, 250.0f*w/h, 0.0f, 250.0f): Esta função é utilizada para estabelecer que a projeção ortográfica, a projeção 2D, será a usada para a imagem 2D que se apresenta na janela de seleção. glMatrixMode(GL_PROJECTION): Esta função indica que as próximas alterações irão mudar como o observador verá a janela. glLoadIdentity(): Esta função estabelece que a matriz atual será inicializada juntamente com a matriz identidade. Exercícios Atividade do objetivo 1: Quais das afirmativas são verdadeiras quanto as vantagens da API OpenGL. ( ) O OpenGL é portável. ( ) OpenGL permite animações e temporização ( ) É uma API de plataforma cruzada (cross-platform). Gabarito comentado: ( V ) O OpenGL é portável. Sim, porque é possível utilizar as mesmas funções em diferentes plataformas. ( F ) OpenGL permite animações e temporização. Não, O OpenGL não fornece funções para animações, temporização, E/S de arquivo, processamento de formato de arquivo de imagem e assim por diante. O OpenGL está preocupado apenas com a renderização. O GLUT, biblioteca usada para criar uma janela do OpenGL, não é OpenGL. Não faz parte do OpenGL. ( V ) É uma API de plataforma cruzada (cross-platform). Sim, pois pode ser usada em várias plataformas, como Windows, Mac e alguns dispositivos portáteis. Atividade do objetivo 2: Vimos que no estudo de uma API mais complexa, como a OpenGL, observar programas prontos como exemplo é essencial para o aprendizado. O programa abaixo desenha uma linha diagonal preta. Diga quais linhas alterar para desenhar uma linha horizontal vermelha. Antes Depois Gabarito As alterações devem ser feitas na função void display(). Na função glColor3f() o primeiro parâmetro corresponde ao vermelho, que deve sair de 0 para 1. Assim, glColor3f (1.0, 0.0, 0.0); Na função glVertex2() a coordenada final pode ser alterada para manter a componente y inalterada em relação a coordenada inicial, mantendo a linha horizontal. Assim, glVertex2i(40,200); glVertex2i(200,200); Atividade do objetivo 4: Qual das afirmações abaixo podem ser definidas como desvantagens do Opengl em relação a outras APIs gráficas? A)Por natureza, OpenGL é restrita a um único sistema operacional. B)Para chamadas de desenho e alterações de estado, o OpenGL possui uma sobrecarga de CPU maior do que as outras APIs gráficas. Gabarito comentado: A) Não é verdade. OpenGL é um padrão da indústria. Guiado por um consórcio independente, o OpenGL Architecture Review Board supervisiona a especificação OpenGL, tornando este o único padrão gráfico verdadeiramente aberto, neutro em fornecedores e multiplataforma. B) Isso não pode ser afirmado. Muitos concordam que para algumas aplicações o OpenGL tende a executar um pouco mais lentamente do que DirectX, por exemplo, por causa da robustez. Mas é claro, isso é discutível. O certo é que não existe uma referência de teste (benchmark) verdadeira para tudo. Atividade do objetivo 5: Nos exemplos dados nesta aula nós usamos o kit de ferramentas utilitárias GLUT, que é um sistema baseado em eventos. Como foi realizada esta interação do OpenGL com o GLUT? Gabarito comentado: A interação é baseada na definição de um número de funções de retorno de chamada (callback), que serão chamadas pelo sistema quando o evento especificado ocorrer. Por exemplo, movimentos do mouse, cliques no botão do mouse, teclas sendo digitadas etc. Para o desenho com GLUT, uma função de retorno de chamada, a função de display (glutDisplayFun) usa esse retorno de chamada quando precisa redesenhar a tela. Próximos passos • Na sequência verificaremos as bibliotecas em C para captura de eventos de teclado e mouse, incluindo acesso a registros usando C. Captura de eventos de teclado e mouse Quando interagimos com um computador, seja este um PC, vídeo game, smartphone ou Smart TV (dentre outros que nos cercam) estamos frequentemente solicitando que estes capturem eventos. A captura de eventos permite que sua solicitação para o equipamento, seja esta a atuação do joystick, uma troca de canal ou o acesso a um aplicativo, possa ser atendida de forma quase imediata. Nesta aula veremos como esta eficiência para atender a sua solicitação é possível e como programá-la em C para captura de eventos de teclado e mouse. Veremos que esta captura, em sistemas operacionais mais antigos, fazem o acesso a registros, demonstrando uma característica expressiva da programação de software básico. Captura de eventos e interrupção em programação Capturar eventos é a uma das formas mais comuns de estabelecer uma interface entre os usuários e um programa desenvolvido por você. Em programação, um evento é algo que ocorre como resultado de uma ação do usuário ou de outra fonte, como clicar em botão do mouse ou pressionar uma tecla no teclado. Um manipulador de eventos é uma rotina usada para lidar com o evento, permitindo que um programador escreva código que será executado quando o evento ocorrer. Além de eventos de teclado e mouse, outros exemplos de eventos comuns são: • Um navegador da web carregando completamente uma página da web. • Um arquivo sendo criado ou modificado em um sistema de arquivos. • Um sensor de hardware, como uma webcam ou microfone, recebendo entrada sensorial. • A chegada do tráfego de rede recebido. • A ocorrência de um erro no nível do programa ou sistema. Manipulação de evento em um programa Clicar 1-Usuário interage com a tela Evento 2-Um evento ocorre trataEvento(){ ... } 3-Código em resposta ao evento 4-Alteração da tela e resposta do programa em função do código. Interrupção - IRQ (Interrupt Request Line) Em alguns sistemas, como no antigo MS-DOS, um evento de teclado ou mouse pode provocar uma interrupção. Uma interrupção é um sinal enviado ao processador que interrompe o processo atual. Além de dispositivos de hardware, um software pode gerar uma interrupção. Como exemplo, se você estiver usando um processador de texto e pressionar uma tecla, o programa deverá processar a entrada imediatamente. Digitar "olá" cria cinco solicitações de interrupção, o que permite ao programa exibir as letras digitadas. Da mesma forma, sempre que você clica em um botão do mouse ou toca em uma tela sensível ao toque, envia um sinal de interrupção para o dispositivo. Uma interrupção é enviada ao processador como uma solicitação de interrupção ou IRQ (Interrupt Request Line). Cadadispositivo de entrada possui uma configuração ou prioridade exclusiva de IRQ. Isso evita conflitos e garante que dispositivos de entrada comuns, como teclados e mouses, sejam priorizados. Interrupções de hardware e software As interrupções de software são usadas para manipular erros e exceções que ocorrem enquanto um programa está em execução. Por exemplo, se um programa espera que uma variável seja um número válido, mas o valor é nulo, pode ser gerada uma interrupção para impedir que o programa trave. Ele permite que o programa mude de rumo e lide com o erro antes de continuar. Da mesma forma, uma interrupção pode ser usada para interromper um loop infinito, o que pode criar um vazamento de memória ou fazer com que um programa não responda. As interrupções de hardware e software são processadas por um manipulador de interrupções, também chamado de rotina de serviço de interrupção, ou ISR. Quando um programa recebe uma solicitação de interrupção, o ISR lida com o evento e o programa é retomado. Como as interrupções costumam ser tão breves quanto o pressionamento de tecla ou o clique do mouse, elas geralmente são processadas em poucos milissegundos. Diferença entre evento e interrupção Os conceitos de evento e interrupção oferecem maneiras para o sistema/programa lidar com várias condições que ocorrem durante o desenrolar normal de algum programa e que podem exigir que o sistema/programa faça outra coisa antes de retornar para a tarefa original. No entanto, além dessa semelhança funcional, eles são conceitos muito distintos usados em contextos distintos, em níveis distintos. As interrupções fornecem um dispositivo de baixo nível para interromper o desenrolamento normal de qualquer parte do programa que a CPU esteja trabalhando em um determinado momento e para que a CPU comece a processar as instruções em outro endereço. As interrupções são úteis para lidar com várias situações que exigem o processamento imediato da CPU. Interrupções x Eventos As interrupções são normalmente despachadas por meio de tabelas vetoriais, nas quais a CPU possui um local específico na memória contendo uma matriz de endereços, onde residem determinados manipuladores de interrupção. Modificando o conteúdo da tabela de interrupções, se for permitido, um programa pode redefinir qual manipulador específico será chamado para um determinado número de interrupção. Eventos, por outro lado, são mensagens no nível do sistema/linguagem que podem ser usadas para significar várias situações de hardware ou software, como cliques no mouse, entradas do teclado, mas também no nível do aplicativo, em situações como "Novo registro inserido no banco de dados". Diferentemente das interrupções, com seu comportamento relativamente simples, que é totalmente definido pela CPU, existem vários sistemas de eventos, no nível do sistema operacional, bem como várias estruturas, como por exemplo estruturas do MS Windows, JavaScript, .NET, etc. Todos os sistemas de eventos, embora diferentes em suas implementações, geralmente compartilham propriedades comuns, como o conceito de um manipulador, que é uma função específica do programa designada para lidar com tipos específicos de eventos de fontes diversas. Captura de eventos em programas 16 bits • Como principais periféricos de entrada de um computador, teclado e mouse possuem diversas bibliotecas em C para acesso aos eventos de cliques em suas teclas e botões. Em programas do tipo console, a conhecida função scanf() da biblioteca padrão é um exemplo de acesso a dados provenientes de cliques em um teclado. • No caso do mouse, esta interação não é tão usual nas aplicações tipo console. Aplicações para o console são aquelas executadas numa janela de texto (também conhecida como Prompt do MS-DOS). • Mesmo sendo obsoleto, o acesso ao mouse também pode ser visto nestas condições para um bom entendimento dos programas de software básico. Acesso a mouse em programas tipo console O acesso ao mouse em programas tipo console não é direto, mas através do driver. Usam- se interrupções para obter acesso a esse driver. Cada dispositivo fornecido por um computador possui uma porta exclusiva, que é um valor hexadecimal projetado para ser independente da capacidade de portabilidade do programa. Essas portas são acessadas pelos programas. O mouse tem a porta 0x33 anexada a ele. Também fazemos uso de registros de endereços. Estes são basicamente UNION do tipo REGS definido no cabeçalho "dos.h". Usam-se dois registradores para se comunicar a um driver de dispositivo, um para entrada e outro para saída. Enviamos um valor ao driver de dispositivo através do registro de entrada e recebemos informações nele embutidas no registro de saída. Acesso a mouse em programas tipo console Podemos acessar várias funções do mouse usando diferentes valores de entrada do Registro AX e passando esses valores para a porta do mouse usando uma interrupção. A figura abaixo mostra as estruturas da Union REGS in, out (entrada, saída). As funções AX, BX, CX e DX membros do UNION REGS. Entrada -> Funções executadas com parâmetro de retorno, se houver. 1. AX = 0 -> Obtém o status do mouse (o valor AX = suporte FFFFh está disponível. Valor AX = 0, o suporte não está disponível.) 2. AX = 1 -> Mostrar ponteiro do mouse. 3. AX = 2 -> Ocultar o ponteiro do mouse. 4. AX = 3 -> Posição do Mouse. (CX = Coordenada do x Mouse, DX = Coordenada y do Mouse). 5. AX = 3 -> Botão do mouse pressionado (BX = 0 - nenhuma tecla é pressionada, BX = 1 - botão esquerdo é pressionado, BX = 2 - botão direito é pressionado, BX = 3 - botão central é pressionado). 6. AX = 7 CX = MaxX1 DX = MaxX2 -> Definir limite horizontal. 7. AX = 8 CX = MaxX1 DX = MaxX2 -> Definir limite vertical. Como testar??? Somente programas para Windows 16-bits e DOS permitem o acesso a esses registros. Os compiladores C atuais, de 32 e 64 bits, não terão acesso desta forma aos registros e dados do mouse. Logo, os testes dos códigos a seguir só poderão ser feitos no Turbo C++. https://developerinsider.co/download-turbo-c-for-windows-7-8-8-1- and-windows-10-32-64-bit-full-screen/ #include <dos.h> union REGS in, out; void detecta_mouse () { in.x.ax = 0; int86 (0X33, &in, &out); //invoca a interrupção if (out.x.ax == 0) printf ("\nMouse falhou a inicializacao"); else printf ("\nMouse foi inicializado com sucesso."); } int main () { detecta_mouse (); getch (); return 0; } O programa EX1 disponível na pasta Exemplos dos_openGL disponível no arquivos do teams ao lado declara duas variáveis do tipo union REGS, que é declarada em dos.h. A union REGS contém duas estruturas (struct WORDREGS x, struct BYTEREGS h), como visto na figura 2. Estas duas estruturas contêm algumas variáveis de 1 byte e 2 bytes de comprimento que indiretamente representam Registros da CPU. Ao colocar 0 no registrador ax e invocar a interrupção do mouse (33h), podemos verificar se o driver do mouse está carregado ou não. Usa-se a função int86() para invocar o método interrupt.int86 (), que recebe 3 argumentos: número da interrupção (0x33) e duas variáveis do tipo union REGS. Se o driver do mouse não estiver carregado, ele retornará 0 no registrador ax. Todos os valores de retorno são acessados usando out, por isso temos out.x.ax == 0 na declaração if. Mostrando o mouse O cursor do mouse pode ser usado tanto no modo de texto quanto no modo gráfico. No modo de texto ele se parece como um quadrado, enquanto no modo gráfico se parece como o ponteiro do Windows. No programa abaixo, usamos a função de biblioteca padrão initgraph () para inicializar o sistema gráfico. Essa função recebe 3 argumentos: driver de gráficos, modo de gráfico e caminho para o arquivo do driver. Usando DETECT, que é uma macro definida em "graphics.h", dizemos à função para selecionar um driver adequado. Quando DETECT é usado, não é necessário atribuir nada ao modo gráfico. #include <dos.h> #include <graphics.h> union REGS in, out; void showmouse_graphics () { int gdriver= DETECT, gmode, errorcode; initgraph(&gdriver, &gmode, "c:\\turboc3\\bgi"); in.x.ax = 1; int86 (0X33,&in,&out); getch (); closegraph (); } void detecta_mouse () { in.x.ax = 0; int86 (0X33,&in,&out); //invoca a interrupção if (out.x.ax == 0) printf ("\nMouse falhou a inicializacao"); else printf ("\nMouse foi inicializado com sucesso."); } int main () { detecta_mouse (); showmouse_graphics (); getch (); return 0; } EX2 disponível na pasta Exemplos dos_openGL disponível no arquivos do teams. Verificando que botão do mouse foi pressionado No programa abaixo envia-se o valor 3 para ax e invoca-se a interrupção do mouse. Esta subfunção retorna informações de pressionamento de botão no registro bx. Toda a informação de toque do botão é armazenada nos primeiros 3 bits do registro bx. Então é realizado um AND de bx com 7 para separar os 3 primeiros bits, armazenando-os na variável button. Se o valor do primeiro bit for 1, o botão esquerdo foi pressionado, se o valor for 0, então não foi pressionado. O segundo corresponde ao botão direito e o último ao botão do meio. O programa continua até uma tecla ser apertada - while (!kbhit () ). int main () { detecta_mouse (); showmouse_text (); detecta_clique (); getch (); return 0; } Exercício: Usando o Ex3(TURBO C++) na pasta do Teams construa uma função para limpar a tela ao pressionar o botão do meio. Biblioteca em programas 32 bits A captura de evento associado ao pressionar o teclado ou ao clicar em um botão do mouse é a forma preferencial atualmente de receber essas informações. Para compiladores como o Dev C++, a biblioteca descrita em windows.h possui funções diversas para capturar esses eventos, como a função GetKeyState(). O parâmetro passado é um Virtual-Key Code. (https://docs.microsoft.com/pt-br/windows/desktop/inputdev/virtual-key-codes ) que estipula várias teclas especiais, caracteres e botões do mouse para verificação. https://docs.microsoft.com/pt-br/windows/desktop/inputdev/virtual-key-codes OpenGL para gerenciar eventos de mouse e teclado A biblioteca GLUT, utilizada com OpengL, nos permite criar aplicativos que detectam a entrada do teclado usando as teclas "normais" ou as teclas especiais, bem como toques no mouse. Sempre que quisermos controlar o processamento de um evento, devemos informar antecipadamente ao GLUT qual função executará essa tarefa. Até agora, usamos o GLUT para informar ao sistema do Windows quais funções queríamos executar quando a janela precisava ser redesenhada, por exemplo. As principais funções para realizar estas tarefas estão descritas a seguir. glutKeyboardFunc É usada para informar ao sistema Windows em qual função queremos processar os eventos de toque em teclas "normais". Por teclas normais queremos dizer letras, números, qualquer coisa que tenha um código ASCII. A função usada como argumento para glutKeyboardFunc precisa ter três argumentos. O primeiro fornece o código ASCII da tecla pressionada. Os dois argumentos restantes fornecem a posição do mouse quando a tecla é pressionada. A posição do mouse é relativa ao canto superior esquerdo da área do cliente da janela. glutSpecialFunc Embora as de teclas ASCII sejam muitas, há algumas teclas que você pode usar, por exemplo, as teclas de seta, que podem ser representadas de maneira diferente em vários sistemas. Felizmente, o GLUT nos permite usar essas teclas. Para isso devemos usar a função glutSpecialFunc, que verifica o pressionamento de teclas especiais. Por exemplo, se quisermos verificar se a seta esquerda foi pressionada, podemos usar GLUT_KEY_LEFT. De forma semelhante usamos GLUT_KEY_F1 para a tecla F1, e assim para as demais. A posição do mouse também pode ser identificada. glutMouseFunc Como o nome indica, estabelece eventos de toque no mouse. Os valores possíveis do primeiro parâmetro de entrada, que identifica o botão clicado, são: GLUT_LEFT_BUTTON, GLUT_MIDDLE_BUTTON e GLUT_RIGHT_BUTTON. O segundo parâmetro, do estado do botão, pode ser GLUT_UP ou GLUT_DOWN. Os dois parâmetros restantes indicam a localização do mouse quando o evento de clique ocorreu. glutMotionFunc Esta função identifica movimento no mouse, chamando o função para tratar este evento, quando este movimento ocorre na janela da aplicacão enquanto um ou mais botões do mouse estão pressionados. glutPassiveMotionFunc Também identifica o movimento no mouse, só que enquanto nenhum de seus botões está pressionado. No Próximo programa de exemplo abaixo foram criadas interações de teclado que alteram a imagem de um retângulo desenhado. O retângula muda de cor com as teclas das letras v (para verde) ou a (para amarelo). Sempre que o usuário movimenta o mouse, a posição (x,y) deste é exibida na janela, indicando também se um dos botões está pressionado ou não. Programa Detecta_mouse e teclado (Presente na Pasta do Teams) void MoveMouseComBotaoPressionado(int x, int y) { sprintf(texto, "Botao pressionado (%d,%d)", x, y); glutPostRedisplay(); } void MoveMouse(int x, int y) { sprintf(texto, "(%d,%d)", x, y); glutPostRedisplay(); } int main(int argc, char** argv){ glutInit(&argc, argv); glutInitDisplayMode(GLUT_SINGLE | GLUT_RGB); glutInitWindowSize(350,300); glutInitWindowPosition(10,10); glutCreateWindow("Interacao com Mouse e Teclado"); glutDisplayFunc(Draw); glutReshapeFunc(MudaTamanhoJanela); glutKeyboardFunc(Teclado); glutMouseFunc(Mouse); glutMotionFunc(MoveMouseComBotaoPressionado); glutPassiveMotionFunc(MoveMouse); Inicia(); glutMainLoop(); } #include <freeglut.h> #include <string.h> #include <stdio.h> GLfloat xf, yf, win; GLint view_w, view_h; char texto[30]; GLfloat win, r, g, b; GLint view_w, view_h, primitiva; void Texto(char *string) { glPushMatrix(); // Coloca na pilha da matriz atual glRasterPos2f(-win,win-(win*0.08)); // Posição onde o texto será colocado while(*string) glutBitmapCharacter(GLUT_BITMAP_TIMES_ROMAN_10,*string++); glPopMatrix(); } void Draw(void) { glMatrixMode(GL_MODELVIEW); glLoadIdentity(); glClear(GL_COLOR_BUFFER_BIT); glBegin(GL_POLYGON); glVertex2f(0.0f, 0.0f); glVertex2f(xf, 0.0f); glVertex2f(xf, yf); glVertex2f(0.0f, yf); glEnd(); glColor3f(1.0f,1.0f,1.0f); Texto(texto); glFlush(); } } void Inicia (void) { glClearColor(0.0f, 0.0f, 0.0f, 1.0f); xf=50.0f; yf=50.0f; win=250.0f; } void MudaTamanhoJanela(GLsizei w, GLsizei h) { glViewport(0, 0, w, h); view_w = w; view_h = h; glMatrixMode(GL_PROJECTION); glLoadIdentity(); gluOrtho2D (-win, win, -win, win); void Teclado(unsigned char key, int x, int y) { switch (key) { case 'a':// Azul glColor3f(0.0f, 0.0f, 1.0f); break; case 'v': //Vermelho glColor3f(1.0f, 0.0f, 0.0f); break; } glutPostRedisplay(); } void Mouse(int button, int state, int x, int y) { if (button == GLUT_LEFT_BUTTON) if (state == GLUT_DOWN) { xf = ( (2 * win * x) / view_w) - win; yf = ( ( (2 * win) * (y-view_h) ) / -view_h) - win; } glutPostRedisplay(); } Programa Detecta_mouse e teclado Atividade do objetivo 1: Vimos que o valor 3 para o registro ax invoca a interrupção do mouse, e que esta subfunção retorna informações de posição do mouse nos registros cx (coordenada x) e dx (coordenada y). Escreva uma função que imprima a coordenada do mouse quando se aperta o botão esquerdo do mesmo. Teste no Turbo C++. Gabarito comentado: Identificar funções para uma determinada tarefa, ampliando e adaptando a partir do que já se testou, é uma das habilidades que devem ser desenvolvidas na programação, especialmente em software básico. Baseado nas funções vistas, que acessam registros para capturar eventos do mouse, podemos criar uma função detecta() para executar a tarefa solicitada. void detecta () { while (!kbhit () ) // enquanto o teclado não é acionado { int x,y; in.x.ax = 3; // invoca a interrupção do mouse int86 (0X33, &in, &out); if (out.x.bx == 1) // Se botão esquerdo do mouse apertado { x = out.x.cx; // coordenada x no registro cx y = out.x.dx; // coordenada y no registro dx printf ("\nPosicao|| X - %d Y - %d", x, y); } delay (200); } } Próxima aula Na próxima aula verificaremos as bibliotecas em C para funções de entrada e saída, por console e arquivo. Explore + Realizar o controle de elementos gráficos é o básico para construir jogos. A OpenGL ainda é muito utilizada para esta função. O material abaixo mostra mais sobre a construção de um jogo simples. https://www.ft.unicamp.br/~magic/opengl/animacao-2D.html#ANIMACAO-DESCRICAO Existem outras bibliotecas para realizar elementos gráficos e jogos. Uma delas é a Allegro. O material abaixo apresenta mais saber sobre esta biblioteca. https://aprendendoallegro.tk/index.php https://www.youtube.com/watch?v=NHq58TlWLe0 https://www.ft.unicamp.br/~magic/opengl/animacao-2D.html#ANIMACAO-DESCRICAO https://aprendendoallegro.tk/index.php https://www.youtube.com/watch?v=NHq58TlWLe0
Compartilhar