Após a atualização do meu notebook para Windows 8, a placa de vídeo AMD Radeon não foi instalada corretamente e frequentemente apresentava erro no aplicativo ATI Catalyst Control Center.
O gerenciador de dispositivos exibia o problema na placa de vídeo cujo nome era AMD Radeon HD 7000M. Baixei seu driver direto do site da Sony e também direto do site da AMD, todos sem sucesso.
Todavia, meu notebook tem um aplicativo da Sony que faz atualização do sistema como um todo. Resolvi usar este aplicativo e para a minha surpresa, foi identificada uma outra versão da placa de vídeo sendo a AMD Radeon HD 6470M / 6630M.
Devido a este erro no nome da placa de vídeo apresentado pelo gerenciado de dispositivos do Windows 8, eu erroneamente estava baixando e instalando a versão errada do driver da AMD Radeon HD.
Fica aí a dica para aqueles que estão com o mesmo problema.
sexta-feira, 25 de janeiro de 2013
Atualização para Windows 8
Como profissional da área de tecnologia da informação, tenho a obrigação de experimentar as novidades do mercado, à medida do possível. Próximo do final do mês de janeiro de 2013, data limite para término da promoção de atualização do para o Windows 8, resolvi experimentar e mal sabia o que viria pela frente.
Até então, estava com o Windows 7 Professional e Office 2010, tudo legalizado. Por causa do Office 2010, o Thunderbird (cheio de mensagens de e-mail de várias contas), outros softwares que adquiri e outros tantos gratuitos que estavam devidamente configurados, resolvi fazer a atualização para Windows 8 com a opção para manter dados de usuário e aplicativos instalados. O assistente de atualização da Microsoft indicava que somente um aplicativo não era compatível; então, comprei a licença do Windows 8 e comecei a instalação.
Após longos minutos esperando a finalização do download, a instalação começou, foi até 90% e reiniciou a máquina. Para minha surpresa (que ingênuo!), houve uma mensagem após o reinício indicando "falha na instalação do Windows". O sistema recuperou a instalação do Windows 7 sem problemas (ufa!), mas não deu nenhum indicativo do problema encontrado.
Vasculhei fóruns, inclusive em inglês, e encontrei uma legião de usuário do Windows na mesma situação com a mesma mensagem de erro, porém somente alguns mais insistentes conseguiram resolver o problema, mas cada um de uma forma diferente. Segui algumas dicas, mas continuei com a mesma mensagem de erro após tentar novamente e algumas vezes mais.
Encontrei um artigo no site da Microsoft chamado "Noções Básicas de Falhas e Arquivos de Logs", onde entendi como poderia localizar arquivos de registros da instalação do Windows 8. Os arquivos não fornecem muitas informações objetivas para usuários, ou seja, eles podem servir para alguma coisa para o pessoal de desenvolvimento de suporte da Microsoft, mas não muito para nós. No meu caso, explorei o arquivo setuperr.log e entendi que o erro era porque o sistema não localizava um determinado arquivo no sistema.Veja abaixo alguns registros de erro:
Pelo caminho e nome do arquivo indicado no registro, verifiquei que o arquivo não existia mesmo no meu sistema.
Apelei então para a instalação usando mídia de DVD. O assistente de atualização permite que seja gerado um arquivo no formato ISO para depois gerar a mídia de instalação. Aqui, é necessário ter um software adequado para gravar o arquivo ISO como um DVD (eu tenho o Ashampoo Burning Studio). Comecei agora a instalação pelo DVD e consegui avançar; o error gerado antes não mais surgiu, todavia um novo problema surgiu no mesmo estilo do anterior: "falha na instalação do Windows", sem mais detalhes. Abri de novo o mesmo arquivo de registros de erro e identifiquei um novo problema:
O máximo que entendi destes registros de erro tudo foi um problema qualquer na pasta de dados de aplicativo do Windows Mail. Nem sabia o que era isso, mas supus que fosse alguma coisa ligada ao Windows Live, o qual desinstalei imediatamente, uma vez que ele também não é compatível com o Windows 8. Ainda, fui bisbilhotar a pasta indicada no registro de erro e percebi que ela estava diferente das outras, com as letras (fonte) em verde. Esta característica indicava que a pasta estava criptografada (o Windows 7 Professional permite isso, mas não as versões inferiores do mesmo Windows). Desfiz a criptografia e comecei novamente a atualização para Windows 8.
Finalmente consegui completar a instalação e configuração do Windows 8, depois de vários dias e muitas horas de persistência e paciência. A fabricante do meu notebook (Sony) disponibilizou um pacote de drivers para Windows 8, além de um excelente tutorial de como fazer a migração para Windows 8; baixei o pacote e fiz a instalação. Vale aqui um elogio para a Sony pela facilidade em localizar, baixar e instalar todos os drivers para meu notebook.
Quanto a Microsoft, fica o desapontamento quanto ao suporte técnico; nos fóruns da própria empresa, nenhuma dica realmente útil vinda dos próprios profissionais da Microsoft. As informações relevantes geralmente têm sido publicadas pelos próprios usuários do sistema que conseguiram resolver alguns dos problemas encontrados.
Quanto ao Windows 8, me acostumei rápido com a nova interface gráfica e achei o sistema um pouco mais rápido, comparado ao Windows 7. Os aplicativos instalados anteriormente parecem realmente compatíveis com o novo sistema operacional; estava especialmente preocupado com o Office 2010, pois é uma versão de 32 bits num sistema de 64 bits e encontrei vários relatos de incompatibilidade - por sorte, não foi o meu caso!
Até então, estava com o Windows 7 Professional e Office 2010, tudo legalizado. Por causa do Office 2010, o Thunderbird (cheio de mensagens de e-mail de várias contas), outros softwares que adquiri e outros tantos gratuitos que estavam devidamente configurados, resolvi fazer a atualização para Windows 8 com a opção para manter dados de usuário e aplicativos instalados. O assistente de atualização da Microsoft indicava que somente um aplicativo não era compatível; então, comprei a licença do Windows 8 e comecei a instalação.
Após longos minutos esperando a finalização do download, a instalação começou, foi até 90% e reiniciou a máquina. Para minha surpresa (que ingênuo!), houve uma mensagem após o reinício indicando "falha na instalação do Windows". O sistema recuperou a instalação do Windows 7 sem problemas (ufa!), mas não deu nenhum indicativo do problema encontrado.
Vasculhei fóruns, inclusive em inglês, e encontrei uma legião de usuário do Windows na mesma situação com a mesma mensagem de erro, porém somente alguns mais insistentes conseguiram resolver o problema, mas cada um de uma forma diferente. Segui algumas dicas, mas continuei com a mesma mensagem de erro após tentar novamente e algumas vezes mais.
Encontrei um artigo no site da Microsoft chamado "Noções Básicas de Falhas e Arquivos de Logs", onde entendi como poderia localizar arquivos de registros da instalação do Windows 8. Os arquivos não fornecem muitas informações objetivas para usuários, ou seja, eles podem servir para alguma coisa para o pessoal de desenvolvimento de suporte da Microsoft, mas não muito para nós. No meu caso, explorei o arquivo setuperr.log e entendi que o erro era porque o sistema não localizava um determinado arquivo no sistema.Veja abaixo alguns registros de erro:
2013-01-23 20:37:33, Error CONX [CDeviceBiosBlocks::Generate] Unable to open SDB C:\Users\ALEXAN~1\AppData\Local\Temp\8f2f2112-0329-428a-bb95-b48bc77e51d0\WebSetupExpanded\drvmain.sdb.[gle=0x000000cb] 2013-01-23 20:37:33, Error CONX [wmain] [0x80004005] QueryAppBlock encountered an error gathering bios blocks. 2013-01-23 20:37:33, Error CONX [ConX::Compatibility::Wica::GetCompatibilityInfo] Query bios block returned an error - 1.[gle=0x00000715]
Pelo caminho e nome do arquivo indicado no registro, verifiquei que o arquivo não existia mesmo no meu sistema.
Apelei então para a instalação usando mídia de DVD. O assistente de atualização permite que seja gerado um arquivo no formato ISO para depois gerar a mídia de instalação. Aqui, é necessário ter um software adequado para gravar o arquivo ISO como um DVD (eu tenho o Ashampoo Burning Studio). Comecei agora a instalação pelo DVD e consegui avançar; o error gerado antes não mais surgiu, todavia um novo problema surgiu no mesmo estilo do anterior: "falha na instalação do Windows", sem mais detalhes. Abri de novo o mesmo arquivo de registros de erro e identifiquei um novo problema:
2013-01-24 21:57:27, Error Error READ, 0x0000000B while gathering/applying object: File, C:\Users\Alexandre\AppData\Local\Microsoft\Windows Mail. Will return 0 2013-01-24 21:57:27, Error MIG Error 11 while applying object C:\Users\Alexandre\AppData\Local\Microsoft\Windows Mail. Shell application requested abort 2013-01-24 21:57:27, Error [0x08097b] MIG Abandoning apply due to error for object: C:\Users\Alexandre\AppData\Local\Microsoft\Windows Mail 2013-01-24 21:57:28, Error pUpgLayerDoOnlineApply: Apply operation failed. Error: 0x0000002C
O máximo que entendi destes registros de erro tudo foi um problema qualquer na pasta de dados de aplicativo do Windows Mail. Nem sabia o que era isso, mas supus que fosse alguma coisa ligada ao Windows Live, o qual desinstalei imediatamente, uma vez que ele também não é compatível com o Windows 8. Ainda, fui bisbilhotar a pasta indicada no registro de erro e percebi que ela estava diferente das outras, com as letras (fonte) em verde. Esta característica indicava que a pasta estava criptografada (o Windows 7 Professional permite isso, mas não as versões inferiores do mesmo Windows). Desfiz a criptografia e comecei novamente a atualização para Windows 8.
Finalmente consegui completar a instalação e configuração do Windows 8, depois de vários dias e muitas horas de persistência e paciência. A fabricante do meu notebook (Sony) disponibilizou um pacote de drivers para Windows 8, além de um excelente tutorial de como fazer a migração para Windows 8; baixei o pacote e fiz a instalação. Vale aqui um elogio para a Sony pela facilidade em localizar, baixar e instalar todos os drivers para meu notebook.
Quanto a Microsoft, fica o desapontamento quanto ao suporte técnico; nos fóruns da própria empresa, nenhuma dica realmente útil vinda dos próprios profissionais da Microsoft. As informações relevantes geralmente têm sido publicadas pelos próprios usuários do sistema que conseguiram resolver alguns dos problemas encontrados.
Quanto ao Windows 8, me acostumei rápido com a nova interface gráfica e achei o sistema um pouco mais rápido, comparado ao Windows 7. Os aplicativos instalados anteriormente parecem realmente compatíveis com o novo sistema operacional; estava especialmente preocupado com o Office 2010, pois é uma versão de 32 bits num sistema de 64 bits e encontrei vários relatos de incompatibilidade - por sorte, não foi o meu caso!
segunda-feira, 23 de julho de 2012
IceScrum?
IceScrum é uma ferramenta interessante para gerenciamento do processo ágil de desenvolvimento de software chamado Scrum. Desenvolvido em Java na plataforma web, o IceScrum é um software de código aberto e grátis (download).
Entre algumas ferramentas grátis que testei para auxiliar no gerenciamento do processo de desenvolvimento, o IceScrum foi a ferramenta que me deixou mais confortável porque implementa os conceitos da metodologia Scrum de forma concisa e quase natural.
A versão atual R5#1.2 dispensa maiores configurações para banco de dados, pois utiliza o banco de dados embutido HSQLDB, também baseado em Java. Apesar desta facilidade, outras configurações ainda são necessárias e as instruções apresentada no site não são tão precisas. Tive problemas com as duas opções de instalação, mas consegui colocar em funcionamento apenas a versão 'bundled' após diversas tentativas (mas isso está fora do escopo deste artigo). O fórum de suporte da ferramenta ajudou, mas tem várias respostas dos próprios administradores do fórum sem explicações técnicas sobre o problema, apenas indicando um download para resolvê-lo.
Ainda, qualquer pessoa que acessa o sistema pode fazer um registro, criar um projeto e montar uma equipe para este projeto adicionando usuários cadastrados na ferramenta ao projeto.
Somente após pesquisar no fórum de discussão da ferramenta, descobri que existe um usuário administrador. Este usuário consegue acessar todos os projetos, aparentemente sem restrição, mas não tem o controle dos usuários cadastrados. Isso chegou a ser um problema para mim, pois, aqui, um desenvolvedor chegou a esquecer a identificação e senha da própria conta; eu não tive como pesquisar a sua identificação no sistema, para que mais tarde, o próprio usuário pudesse fazer a sua recuperação de senha.
Gostei bastante da possibilidade de criar estórias por qualquer membro da equipe, ficando estas estórias numa área livre esperando aceitação do dono do projeto ou scrum master. Uma estória pode ser priorizada e também estimadas por 'story points' após aceita. Também é possível adicional testes de aceitação à estórias.
As iterações são programadas de forma fácil, onde as estórias aceitas e estimadas (atribuição de peso) são listadas e adicionadas à iteração via drag-and-drop. A partir de uma estória, criam-se as tarefas que automaticamente assumem a coluna 'Para Fazer' do painel de iteração.
A imagem ao lado mostra o painel de um projeto em andamento; nomes de projeto, de algumas tarefas e de colaboradores foram ofuscados por motivos óbvios! Os post-its das tarefas apresentados no painel podem ser movidos entre as colunas 'Para Fazer', 'Em Andamento' e 'Concluído' via drag-and-drop
Os desenvolvedores do projeto devem mover uma tarefa com estado 'Para Fazer' para a coluna 'Em Andamento'; automaticamente o sistema associa o desenvolvedor à tarefa. Uma vez a tarefa concluída, o post-it deve ser movido para a coluna seguinte. Muito intuitivo!
Em alguns momento, a ferramenta travou, mesmo com mais de 512MB de memória alocada. Apenas dois projetos com pouquíssimas estórias e tarefas estavam cadastradas na ferramenta. Ainda estou acompanhando e analisando a frequência deste tipo ocorrência.
Ainda, mensagens de erro com a conexão com banco de dados foi apresentada, todavia não foi notado maiores problemas além da mensagem.
Entre algumas ferramentas grátis que testei para auxiliar no gerenciamento do processo de desenvolvimento, o IceScrum foi a ferramenta que me deixou mais confortável porque implementa os conceitos da metodologia Scrum de forma concisa e quase natural.
Instalação & Configuração
A instalação da ferramente pode ser feita pela implantação de um arquivo WAR no Tomcat, ou noutro servidor compatível, ou então baixar a versão 'bundled' que já vem com o Tomcat embutido e executar scripts para execução.A versão atual R5#1.2 dispensa maiores configurações para banco de dados, pois utiliza o banco de dados embutido HSQLDB, também baseado em Java. Apesar desta facilidade, outras configurações ainda são necessárias e as instruções apresentada no site não são tão precisas. Tive problemas com as duas opções de instalação, mas consegui colocar em funcionamento apenas a versão 'bundled' após diversas tentativas (mas isso está fora do escopo deste artigo). O fórum de suporte da ferramenta ajudou, mas tem várias respostas dos próprios administradores do fórum sem explicações técnicas sobre o problema, apenas indicando um download para resolvê-lo.
Funcionalidades
Mesmo não registrado no sistema (logado), qualquer pessoa pode visualizar parcialmente os projetos cadastrados. Esta visualização parcial significa ver o painel inicial do projeto, os registros de atividades e incluindo os gráficos, a área livre (sandbox) e a lista do produto (product backlog); também é possível ver a estórias detalhadamente.Ainda, qualquer pessoa que acessa o sistema pode fazer um registro, criar um projeto e montar uma equipe para este projeto adicionando usuários cadastrados na ferramenta ao projeto.
Somente após pesquisar no fórum de discussão da ferramenta, descobri que existe um usuário administrador. Este usuário consegue acessar todos os projetos, aparentemente sem restrição, mas não tem o controle dos usuários cadastrados. Isso chegou a ser um problema para mim, pois, aqui, um desenvolvedor chegou a esquecer a identificação e senha da própria conta; eu não tive como pesquisar a sua identificação no sistema, para que mais tarde, o próprio usuário pudesse fazer a sua recuperação de senha.
Gostei bastante da possibilidade de criar estórias por qualquer membro da equipe, ficando estas estórias numa área livre esperando aceitação do dono do projeto ou scrum master. Uma estória pode ser priorizada e também estimadas por 'story points' após aceita. Também é possível adicional testes de aceitação à estórias.
As iterações são programadas de forma fácil, onde as estórias aceitas e estimadas (atribuição de peso) são listadas e adicionadas à iteração via drag-and-drop. A partir de uma estória, criam-se as tarefas que automaticamente assumem a coluna 'Para Fazer' do painel de iteração.

Os desenvolvedores do projeto devem mover uma tarefa com estado 'Para Fazer' para a coluna 'Em Andamento'; automaticamente o sistema associa o desenvolvedor à tarefa. Uma vez a tarefa concluída, o post-it deve ser movido para a coluna seguinte. Muito intuitivo!
Problemas...
Uma desvantagem da ferramenta é a quantidade de memória alocada para sua execução. O tamanho de 512 MB é a quantidade mínima recomendada, mas eu tive que alocar um pouco mais. Para fazer isso na versão 'bundled' foi preciso modificar os scripts de execução do Tomcat, o que não está prontamente documentado no site da ferramenta!Em alguns momento, a ferramenta travou, mesmo com mais de 512MB de memória alocada. Apenas dois projetos com pouquíssimas estórias e tarefas estavam cadastradas na ferramenta. Ainda estou acompanhando e analisando a frequência deste tipo ocorrência.
Ainda, mensagens de erro com a conexão com banco de dados foi apresentada, todavia não foi notado maiores problemas além da mensagem.
Conclusão
IceScrum, versão R5#1.2, é uma ferramenta com uma interface gráfica agradável e até um tanto intuitiva. Sua instalação não foi tranquila para mim e a documentação do site está desatualizada; todavia o fórum de discussão pode ajudar. A alocação de memória superior se comparada à outras ferramentas não chega a ser um impeditivo real, já os problemas de travamento da ferramenta e mensagem de erro de conexão com o banco de dados deixa uma impressão ruim e uma sensação de insegurança para adotar a ferramente integralmente.segunda-feira, 2 de julho de 2012
Configurando Launch4J para Maven
Launch4J é um aplicativo famoso usado para transformar arquivos JAR em arquivos executáveis para o sistema operacional Windows. É natural que se queira utilizar este aplicativo em conjunto com o Maven para gerar os arquivos finais do projeto para distribuição. Neste cenário, a intenção é atualizar sempre o número da versão e build do aplicativo automaticamente, antes mesmo de gerar o arquivo executável.
A primeira opção para rodar o Launch4J integrado ao Maven é a utilização de plugin. Nos links de referência, no final deste artigo, estão listados alguns websites para o plugin Launch4J para Maven e outros links com exemplos de uso.
A utilização do plugin pode ser mais limitada (ainda não testei) e ainda talvez se deseja utilizar a configuração já existentes do Launch4J do projeto, sem correr o risco de perder alguma configuração; este motivo justificaria a utilização do Launch4J era como um tarefa do Ant. Não vou ensinar como criar este arquivo de configuração, pois já está razoavelmente documentado no próprio website do Launch4J. Assim, com um mínimo de adaptação, o Launch4J fica pronto para o Maven, como uma tarefa do Ant, como mostra o código abaixo:
Aqui, utilizei o plug-in Antrun. Da linha 13 à linha 18 estão as configurações das tarefas Ant para execução.
A linha 13 copia o arquivo de configuração do Launch4J para um arquivo temporário, que é manipulado na sequência (linha 14). Neste arquivo, todas as sequências de caracteres 0.0.0.0 serão substituídas pelo número da versão do projeto (variável do próprio Maven: ${project.version}) e o número da build (variável do Hudson: ${BUILD_NUMBER}). Só lembrando, caso não esteja trabalhando com o Hudson, você deve remover esta última variável da composição dos números da versão do seu aplicativo.
A definição da tarefa do Launch4J é feita na linha 15. Pressupõe-se que o aplicativo esteja instalado no ambiente de execução do Maven. Aqui, a variável ${launch4j.dir} fora definida anteriormente no arquivo pom.xml do projeto com o caminho da instalação do aplicativo. Observe que tal variável aparece duas vezes no atributo 'classpath' desta linha.
Na sequência, linha 16, vem a chamada da própria tarefa definida da linha anterior. Esta tarefa demanda 2 atributos, sendo o nome do arquivo JAR e o nome do executável que será gerado. As variáveis utilizadas aqui são do próprio Maven.
As linhas 17 e 18 fazem uma limpeza: remove o arquivo JAR, que agora já está encapsulado como um arquivo executável, e depois remove o temporário criado na linha 13.
http://ant.apache.org/
http://9stmaryrd.com/tools/launch4j-maven-plugin/
http://mvnrepository.com/artifact/com.akathist.maven.plugins.launch4j/launch4j-maven-plugin
http://stackoverflow.com/questions/6060560/trying-to-integrate-launch4j-in-a-maven-project-using-alakai-plugin
A primeira opção para rodar o Launch4J integrado ao Maven é a utilização de plugin. Nos links de referência, no final deste artigo, estão listados alguns websites para o plugin Launch4J para Maven e outros links com exemplos de uso.
A utilização do plugin pode ser mais limitada (ainda não testei) e ainda talvez se deseja utilizar a configuração já existentes do Launch4J do projeto, sem correr o risco de perder alguma configuração; este motivo justificaria a utilização do Launch4J era como um tarefa do Ant. Não vou ensinar como criar este arquivo de configuração, pois já está razoavelmente documentado no próprio website do Launch4J. Assim, com um mínimo de adaptação, o Launch4J fica pronto para o Maven, como uma tarefa do Ant, como mostra o código abaixo:
<plugin> <groupId>org.apache.maven.plugins</groupId> <artifactId>maven-antrun-plugin</artifactId> <executions> <execution> <id>launch4j</id> <phase>package</phase> <goals> <goal>run</goal> </goals> <configuration> <tasks> <copy file="config.xml" tofile="config-temp.xml"/> <replace file="config-temp.xml" token="0.0.0.0" value="${project.version}.${BUILD_NUMBER}"/> <taskdef name="launch4j" classname="net.sf.launch4j.ant.Launch4jTask" classpath="${launch4j.dir}/launch4j.jar:${launch4j.dir}/lib/xstream.jar" /> <launch4j configFile="./launch4j-client-temp.xml" jar="${project.build.directory}\my-application-${project.version}.jar" outfile="${project.build.directory}\my-application.exe"/> <delete file="${project.build.directory}\my-application-${project.version}.jar"/> <delete file="config-temp.xml"/> </tasks> </configuration> </execution> </executions> </plugin>
Aqui, utilizei o plug-in Antrun. Da linha 13 à linha 18 estão as configurações das tarefas Ant para execução.
A linha 13 copia o arquivo de configuração do Launch4J para um arquivo temporário, que é manipulado na sequência (linha 14). Neste arquivo, todas as sequências de caracteres 0.0.0.0 serão substituídas pelo número da versão do projeto (variável do próprio Maven: ${project.version}) e o número da build (variável do Hudson: ${BUILD_NUMBER}). Só lembrando, caso não esteja trabalhando com o Hudson, você deve remover esta última variável da composição dos números da versão do seu aplicativo.
A definição da tarefa do Launch4J é feita na linha 15. Pressupõe-se que o aplicativo esteja instalado no ambiente de execução do Maven. Aqui, a variável ${launch4j.dir} fora definida anteriormente no arquivo pom.xml do projeto com o caminho da instalação do aplicativo. Observe que tal variável aparece duas vezes no atributo 'classpath' desta linha.
Na sequência, linha 16, vem a chamada da própria tarefa definida da linha anterior. Esta tarefa demanda 2 atributos, sendo o nome do arquivo JAR e o nome do executável que será gerado. As variáveis utilizadas aqui são do próprio Maven.
As linhas 17 e 18 fazem uma limpeza: remove o arquivo JAR, que agora já está encapsulado como um arquivo executável, e depois remove o temporário criado na linha 13.
Conclusão
A solução apresentada para se trabalhar com Launch4J e Maven atende aqueles que estão começando a trabalhar tanto com um ou outro destes aplicativos, sem exigir muita configuração por parte Maven. O plugin Antrun utilizado para fazer toda a configuração é da Apache e portanto se espera uma compatibilidade com as futuras versões do próprio Maven, facilitando assim uma possível atualização de versão.Referências
http://launch4j.sourceforge.net/http://ant.apache.org/
http://9stmaryrd.com/tools/launch4j-maven-plugin/
http://mvnrepository.com/artifact/com.akathist.maven.plugins.launch4j/launch4j-maven-plugin
http://stackoverflow.com/questions/6060560/trying-to-integrate-launch4j-in-a-maven-project-using-alakai-plugin
Jogo da Memória em JavaFX 2.1
Aqui, disponibilizo o código fonte de um jogo da memória feito em JavaFX 2.1. O código foi desenvolvido pelo NetBeans 7.1.1. O arquivo compactado contém todo o código fonte, arquivos e áudio e um arquivo JAR que consiste no jogo pronto para ser executado. Ao clicar no botão ou no link para download, você será direcionado para o Google Drive e todos os arquivos do projeto serão listados. Para fazer efetivamente o download, tecle CTRL+S ou vá no menu 'File' e selecione a opção 'Download' para fazer um único download de todos os arquivos.
Vale lembrar que para compilar o jogo, você precisa do JDK 6 ou superior com o módulo para JavaFX, que pode ser baixado pelo site da Oracle. Se você possui o JDK 7 atualizado, então o JavaFX já está incorporado.
No código deste jogo, vocês verão a criação de formas, aplicação de transformações e efeitos, animação sincronizada com áudio e interação com usuário. Tudo isso já foi descrito nos artigos anteriores, de forma didática.
Este jogo da memória é baseado naquele famoso jogo eletrônico da década de 80 chamado Genius. Nesta implementação, a lógica basicamente é a repetição pelo usuário de uma sequência determinada pelo jogo. A sequência pode ser mais rápida ou mais lenta, até atingir uma sequência de 10, começando sempre com 4.
Durante o jogo, é sempre informado a sequência criada pelo sistema e quando o usuário deve iniciar sua interação. As mensagens são sempre exibidas no centro do círculo e desaparecem após 3ms com efeito de 'fading'.
Ao iniciar o jogo, o botão fica desabilitados até a sua finalização. Todavia, o controle para modificar a velocidade do jogo continua habilitado.
A sequência criada pelo jogo é apresentada ao usuário pela animação de cada quarto de círculo, causando a sensação de que fora ligado/aceso e depois apagado. Aqui foi usado o RadialGradient para produzir o efeito desejado, ou seja, para que mais ou menos no centro de cada forma fosse mais claro e no restante mais escuro. Ainda, para cada cor do círculo existe um som associado, executado de forma síncrona com a animação.
Durante a exibição automática da sequência criada pelo jogo, o usuário não tem como interagir com o sistema (exceto mudando a velocidade do jogo).
Após ser informado pelo jogo, com a mensagem 'Sua vez!', o usuário pode então tentar repetir a sequência criada. Não foi criado um tempo limite (timeout) para início da interação do usuário.
Caso o usuário erre a sequência exibida pelo jogo, um som, uma mensagem e efeito de 'fading' do círculo e da mensagem são executados paralelamente. Após 3ms, o jogo volta ao estado inicial, habilitando o botão inciar, pronto para um novo jogo.
Se o usuário conseguir repetir a sequência de 10, sem errar, o jogo também emite som, exibe mensagem e um efeito de rotação de 360 graus horário. Da mesma forma, após 3ms, o jogo volta ao estado inicial, habilitando o botão inciar, pronto para um novo jogo.
Para finalizar, não posso deixar de referenciar o artigo de João Paulo chamado "Genius em C#". Neste artigo, o autor também disponibiliza o código-fonte do seu jogo, junto com arquivos de áudio. Estes mesmos arquivos de áudio são utilizados neste exemplo em JavaFX.
Vale lembrar que para compilar o jogo, você precisa do JDK 6 ou superior com o módulo para JavaFX, que pode ser baixado pelo site da Oracle. Se você possui o JDK 7 atualizado, então o JavaFX já está incorporado.
No código deste jogo, vocês verão a criação de formas, aplicação de transformações e efeitos, animação sincronizada com áudio e interação com usuário. Tudo isso já foi descrito nos artigos anteriores, de forma didática.
Este jogo da memória é baseado naquele famoso jogo eletrônico da década de 80 chamado Genius. Nesta implementação, a lógica basicamente é a repetição pelo usuário de uma sequência determinada pelo jogo. A sequência pode ser mais rápida ou mais lenta, até atingir uma sequência de 10, começando sempre com 4.
Durante o jogo, é sempre informado a sequência criada pelo sistema e quando o usuário deve iniciar sua interação. As mensagens são sempre exibidas no centro do círculo e desaparecem após 3ms com efeito de 'fading'.
Ao iniciar o jogo, o botão fica desabilitados até a sua finalização. Todavia, o controle para modificar a velocidade do jogo continua habilitado.

Durante a exibição automática da sequência criada pelo jogo, o usuário não tem como interagir com o sistema (exceto mudando a velocidade do jogo).
Após ser informado pelo jogo, com a mensagem 'Sua vez!', o usuário pode então tentar repetir a sequência criada. Não foi criado um tempo limite (timeout) para início da interação do usuário.

Se o usuário conseguir repetir a sequência de 10, sem errar, o jogo também emite som, exibe mensagem e um efeito de rotação de 360 graus horário. Da mesma forma, após 3ms, o jogo volta ao estado inicial, habilitando o botão inciar, pronto para um novo jogo.
Para finalizar, não posso deixar de referenciar o artigo de João Paulo chamado "Genius em C#". Neste artigo, o autor também disponibiliza o código-fonte do seu jogo, junto com arquivos de áudio. Estes mesmos arquivos de áudio são utilizados neste exemplo em JavaFX.
quinta-feira, 28 de junho de 2012
Formas, Transformações e Efeitos em JavaFX 2.1
Brincando com JavaFX, versão 2.1, desenvolvi um jogo de memória para exercitar diversos conceitos do framework. Neste artigo, não descrevo exatamente o desenvolvimento do jogo, mas simplesmente a criação da forma básica, a aplicação de transformações nesta forma para se obter o resultado final e ainda a aplicação de efeito de iluminação para criar a ilusão de volume.
Somente para contextualizar, jogo em questão é uma tentativa de reproduzir (aqui neste artigo, visualmente pelo menos) aquele jogo eletrônico chamado de Genius, famoso na década de 80. Veja na Wikipedia mais sobre esse jogo. Ainda, em vários outros sites é possível encontrar várias versões online para jogar.
O jogo tem a forma de uma rosquinha de quarto partes coloridas. Cada parte vou chamar de um quarto de círculo.
Produzir a forma da figura ao lado no JavaFX é muito simples: basta criar dois círculos com raios diferentes e integrar estas duas formas para produzir a forma de uma rosquinha. A partir desta forma, agora, deve-se executar a intersecção com um retângulo cujos lados devem ter valor igual ao maior raio dos círculos criados anteriormente (então estamos falando de um quadrado, na verdade).
O código abaixo traduz tudo o que foi escrito acima. Ler o código é mais fácil que ler qualquer outra explicação.
Adicionar uma cor à forma criada não bastaria para deixá-la mais interessante visualmente. Além da cor, um efeito de luz é necessário para dar à forma um efeito tridimensional, como mostra a figura ao lado.
Em JavaFX, Light representa um tipo/fonte de luz enquanto Lighting representa o efeito desta luz sobre uma forma.
Abaixo, segue o código, com comentários, para produzir o efeito apresentadona figura ao lado.
Para completar o círculo, primeiramente deve-se criar 4 vezes a forma de um quarto de círculo, atribuir uma cor distinta e o mesmo efeito de luz e iluminação às formas. Depois, é necessário rotacionar as formas para obter cada quarto de círculo na devida posição para completar o círculo, ou seja, nas posições noroeste, nordeste, sudoeste e sudeste. Como a primeira forma já ocupa a posição sudeste, para obter as outras posições deve-se rotacionar as demais formas em 90, 180 e 270.
A rotação é suficiente para montar o círculo desejado para o jogo, mas sua exibição ainda não é adequada pois não está centralizada. Para conseguir este resultado, cada forma tem que ser transladada em +/- 50 pixels, de acordo com sua rotação.
O código abaixo mostra o que foi descrito acima. Vale lembrar que as variáveis donut, r1 e lighting já foram instanciadas e descritas anteriormente.
O layout StackPane é bem adequado para exibir as formas criadas, pois exibe cada uma sobreposta e, como a rotação já foi realizada, elas serão serão adequadamente sobrepostas e formarão o círculo esperado.
Ao lado, segue a imagem com o resultado final: um círculo formado de quatro partes com um certo volume aparentando uma forma tridimensional.
Ainda falta criar muita coisa para um jogo, mas o mais importante é também permitir a interação do usuário com cada forma separadamente. Em outras palavras, cada quarto do círculo precisa estar pronto para receber eventos de mouse e executar uma animação. Esta animação viria a ser a sensação de acender rapidamente e apagar mais suavemente cada quarto de círculo.
Cada quarto de círculo de capturar eventos de mouse quando o usuário clicar sobre a forma. Para tanto, precisamos definir uma classe que implemente a interface EventHandler<T extends Event>. note que esta interface pede a definição de um tipo genérico, que neste caso deve ser qualquer classe que implemente a interface Event. Como a intenção é capturar eventos de mouse, então esta classe é a MouseEvent. O código abaixo demonstra a criação e instanciação de uma classe anônima que implementa a interface requerida para a captura de eventos de mouse.
Observe que, uma vez o evento capturado, a origem do evento é recuperada e, a partir de um conversão explícita para Shape, pega-se a cor da forma. Então é gerada uma saída no console com o valor, em hexadecimal, da cor.
Até aqui, simplesmente foi definida e instanciada uma classe anônima para tratar eventos de mouse. Agora, precisa fazer com que cada forma trate o evento de clique de mouse com esta instância. O código abaixo mostra o que deve ser feito:
Neste exemplo, pela interface gráfica o usuário não tem ainda nenhuma percepção que o quarto de círculo recebeu o evento do mouse. O ideal é que seja executada uma animação.
A animação deve ser aquela que dê a sensação para o usuário de que a forma clicada acenda repentinamente e apague gradualmente durante um certo período e tempo. Ainda, a execução de áudio durante a animação torna a interação com o usuário mais interessante.
Veja aqui, neste meu outro artigo chamado "JavaFX Animation and Media Synchronization", como criar uma animação simples e fazer a sincronização com o áudio.
Somente para contextualizar, jogo em questão é uma tentativa de reproduzir (aqui neste artigo, visualmente pelo menos) aquele jogo eletrônico chamado de Genius, famoso na década de 80. Veja na Wikipedia mais sobre esse jogo. Ainda, em vários outros sites é possível encontrar várias versões online para jogar.
Formas

Produzir a forma da figura ao lado no JavaFX é muito simples: basta criar dois círculos com raios diferentes e integrar estas duas formas para produzir a forma de uma rosquinha. A partir desta forma, agora, deve-se executar a intersecção com um retângulo cujos lados devem ter valor igual ao maior raio dos círculos criados anteriormente (então estamos falando de um quadrado, na verdade).
O código abaixo traduz tudo o que foi escrito acima. Ler o código é mais fácil que ler qualquer outra explicação.
Circle c1 = new Circle(100); Circle c2 = new Circle(50); Shape donut = Shape.subtract(c1, c2); Rectangle r1 = new Rectangle(100, 100); Shape quarter = Shape.intersect(donut, r1);
Efeito de Iluminação

Em JavaFX, Light representa um tipo/fonte de luz enquanto Lighting representa o efeito desta luz sobre uma forma.
Abaixo, segue o código, com comentários, para produzir o efeito apresentadona figura ao lado.
// Cria-se uma luz Light.Distant light = new Light.Distant(); light.setAzimuth(-135.0); light.setElevation(60); // Com esta fonte de luz, cria-se a iluminação Lighting lighting = new Lighting(light); lighting.setSurfaceScale(2.0); // A cor e iluminação é aribuída à forma quarter.setFill(Color.BLUE); quarter.setEffect(lighting);
Rotação & Translação
Para completar o círculo, primeiramente deve-se criar 4 vezes a forma de um quarto de círculo, atribuir uma cor distinta e o mesmo efeito de luz e iluminação às formas. Depois, é necessário rotacionar as formas para obter cada quarto de círculo na devida posição para completar o círculo, ou seja, nas posições noroeste, nordeste, sudoeste e sudeste. Como a primeira forma já ocupa a posição sudeste, para obter as outras posições deve-se rotacionar as demais formas em 90, 180 e 270.
A rotação é suficiente para montar o círculo desejado para o jogo, mas sua exibição ainda não é adequada pois não está centralizada. Para conseguir este resultado, cada forma tem que ser transladada em +/- 50 pixels, de acordo com sua rotação.
O código abaixo mostra o que foi descrito acima. Vale lembrar que as variáveis donut, r1 e lighting já foram instanciadas e descritas anteriormente.
// Quatro formas iguais Shape quarter1 = Shape.intersect(donut, r1); Shape quarter2 = Shape.intersect(donut, r1); Shape quarter3 = Shape.intersect(donut, r1); Shape quarter4 = Shape.intersect(donut, r1); // Posição NOROESTE quarter1.setEffect(lighting); quarter1.setFill(Color.BLUE); quarter1.getTransforms().add(new Rotate(180)); quarter1.getTransforms().add(new Translate(-50,-50)); // Posição NORDESTE quarter2.setEffect(lighting); quarter2.setFill(Color.RED); quarter2.getTransforms().add(new Rotate(270)); quarter2.getTransforms().add(new Translate(-50,50)); // Posição SUDESTE - não precisa rotacionar quarter3.setEffect(lighting); quarter3.setFill(Color.YELLOW); quarter3.getTransforms().add(new Translate(50,50)); // Posição SUDOESTE quarter4.setEffect(lighting); quarter4.setFill(Color.GREEN); quarter4.getTransforms().add(new Rotate(90)); quarter4.getTransforms().add(new Translate(50,-50));
O layout StackPane é bem adequado para exibir as formas criadas, pois exibe cada uma sobreposta e, como a rotação já foi realizada, elas serão serão adequadamente sobrepostas e formarão o círculo esperado.
public void start(Stage primaryStage) { /** * Todo código anterior ... */ StackPane root = new StackPane(); root.getChildren().add(quarter1); root.getChildren().add(quarter2); root.getChildren().add(quarter3); root.getChildren().add(quarter4); primaryStage.setScene(new Scene(root, 300, 250)); primaryStage.show(); }

Ainda falta criar muita coisa para um jogo, mas o mais importante é também permitir a interação do usuário com cada forma separadamente. Em outras palavras, cada quarto do círculo precisa estar pronto para receber eventos de mouse e executar uma animação. Esta animação viria a ser a sensação de acender rapidamente e apagar mais suavemente cada quarto de círculo.
Interação com Usuário
Cada quarto de círculo de capturar eventos de mouse quando o usuário clicar sobre a forma. Para tanto, precisamos definir uma classe que implemente a interface EventHandler<T extends Event>. note que esta interface pede a definição de um tipo genérico, que neste caso deve ser qualquer classe que implemente a interface Event. Como a intenção é capturar eventos de mouse, então esta classe é a MouseEvent. O código abaixo demonstra a criação e instanciação de uma classe anônima que implementa a interface requerida para a captura de eventos de mouse.
EventHandler<MouseEvent> mouseEvent = new EventHandler<MouseEvent>(){ @Override public void handle(MouseEvent arg0) Paint color = ((Shape)arg0.getSource()).getFill(); System.out.println("cor: " + color.toString()); } };
Observe que, uma vez o evento capturado, a origem do evento é recuperada e, a partir de um conversão explícita para Shape, pega-se a cor da forma. Então é gerada uma saída no console com o valor, em hexadecimal, da cor.
Até aqui, simplesmente foi definida e instanciada uma classe anônima para tratar eventos de mouse. Agora, precisa fazer com que cada forma trate o evento de clique de mouse com esta instância. O código abaixo mostra o que deve ser feito:
quarter1.setOnMouseClicked(mouseEvent); quarter2.setOnMouseClicked(mouseEvent); quarter3.setOnMouseClicked(mouseEvent); quarter4.setOnMouseClicked(mouseEvent);
Neste exemplo, pela interface gráfica o usuário não tem ainda nenhuma percepção que o quarto de círculo recebeu o evento do mouse. O ideal é que seja executada uma animação.
Animação & Mídia
A animação deve ser aquela que dê a sensação para o usuário de que a forma clicada acenda repentinamente e apague gradualmente durante um certo período e tempo. Ainda, a execução de áudio durante a animação torna a interação com o usuário mais interessante.
Veja aqui, neste meu outro artigo chamado "JavaFX Animation and Media Synchronization", como criar uma animação simples e fazer a sincronização com o áudio.
JavaFX Animation and Media Synchronization
I've been experiencing JavaFX 2.1 lately and I've created pieces of code to work some concepts out. One of those is how to synchronize animation and media (audio, more precisely). My fisrt shot was to create instances of a Timeline, a MediaPlayer and then invoke the play() method of both instances sequentially. That solution seems to work rather nice since you have just one anination and one audio to play. Although, what if you have a sequence of anination and audio to play?
An instance of SequentialTransition fits perfectly if you want to play a row of aninations, one right after the other. And an instance of ParallelTransition plays animations at the same time, or at least concurrently. To get things more interesting, you can create instances of ParallelTransition and add them to an instance of SequentialTransition, or the other way around. Both types accepts instances of any type that extends Animation, which is an abstract class of JavaFX. Timeline, SequentialTransition and ParallelTransition themselves, and other transitions all extend Animation, but MediaPlayer don't! So I had to figure out how to synchronize animation and media simultaneously and then play them in a sequence of animations and medias.
Now, the color variable instances have to change and that's the animation we're talking about. Here, the Timeline comes into play.
Two colors is picked up to make the transition. Then, an instance of Timeline is created and a sequence of KeyFrame instances is added to it. Pay attention to the pairs of KeyFrame instances: each pair handle a color within a period of time, i.e., Duration instances. Besides Duration instance, the KeyFrame contructor demands a KeyValue instance as well. That one takes in a color variable instance and a start color. So, one KeyFrame instance defines that a variable is set to a certain value at a certain period of time and along another KeyFrame instance, such value is interpolated to another one until another period of time.
An instance of SequentialTransition fits perfectly if you want to play a row of aninations, one right after the other. And an instance of ParallelTransition plays animations at the same time, or at least concurrently. To get things more interesting, you can create instances of ParallelTransition and add them to an instance of SequentialTransition, or the other way around. Both types accepts instances of any type that extends Animation, which is an abstract class of JavaFX. Timeline, SequentialTransition and ParallelTransition themselves, and other transitions all extend Animation, but MediaPlayer don't! So I had to figure out how to synchronize animation and media simultaneously and then play them in a sequence of animations and medias.
Animation
First, let's create a simple animation using Timeline that changes colors of a certain shape. The execution of such animation takes 5 seconds and color changes smoothly. The piece of code below just creates a rectangle and other instances to represent each color using the RGB color system (Red, Green and Blue). An anonimous class is also created and instanciated which implements the ChangeListener interface; here is where the color of the shape changed. Then, the listener instance is added to each color variable instance.final Rectangle anyShape = new Rectangle(250, 200); final DoubleProperty redColor = new SimpleDoubleProperty(); final DoubleProperty greenColor = new SimpleDoubleProperty(); final DoubleProperty blueColor = new SimpleDoubleProperty(); ChangeListener colorListener = new ChangeListener() { @Override public void changed(ObservableValue arg0, Object arg1, Object arg2) { anyShape.setFill(Color.color(redColor.doubleValue(), greenColor.doubleValue(), blueColor.doubleValue())); } }; redColor.addListener(colorListener); greenColor.addListener(colorListener); blueColor.addListener(colorListener);
Now, the color variable instances have to change and that's the animation we're talking about. Here, the Timeline comes into play.
Two colors is picked up to make the transition. Then, an instance of Timeline is created and a sequence of KeyFrame instances is added to it. Pay attention to the pairs of KeyFrame instances: each pair handle a color within a period of time, i.e., Duration instances. Besides Duration instance, the KeyFrame contructor demands a KeyValue instance as well. That one takes in a color variable instance and a start color. So, one KeyFrame instance defines that a variable is set to a certain value at a certain period of time and along another KeyFrame instance, such value is interpolated to another one until another period of time.
Color startColor = Color.BLUEVIOLET; Color endColor = Color.YELLOWGREEN; Timeline animation = new Timeline(); animation.getKeyFrames().addAll(new KeyFrame(new Duration(0.0), new KeyValue(redColor, startColor.getRed())), new KeyFrame(new Duration(5000.0), new KeyValue(redColor, endColor.getRed())), new KeyFrame(new Duration(0.0), new KeyValue(greenColor, startColor.getGreen())), new KeyFrame(new Duration(5000.0), new KeyValue(greenColor, endColor.getGreen())), new KeyFrame(new Duration(0.0), new KeyValue(blueColor, startColor.getBlue())), new KeyFrame(new Duration(5000.0), new KeyValue(blueColor, endColor.getBlue()))); animation.play();
Audio
Time to load an audio file and make it play too. The piece of code below does so. The audio file here is inside the JAR file. First, the URL to the audio file is retrieved and then the toExternalForm() method is invoked to get the real path, otherwise, it will not work when the application is executed by the JAR file itself (it will work only within the development IDE).URL soundURL = this.getClass().getResource("/resource/audio.wav"); final MediaPlayer mediaPlayer = new MediaPlayer(new Media(soundURL.toExternalForm())); mediaPlayer.play();
Synchronizing Animation and Audio
Since ParallelTransition does not accept a MediaPlayer instance (which makes sense), animation and media synchronization has to have its own way. Actually, Timeline works it out by itself, along KeyFrame and EventHandler instances. The KeyFrame constructor, besides a Duration instance, also accepts an instance of EventHandler. So, at start time, an EventHandler instance must be set, as well as at stop time. The piece of code below shows how to create instances of EventHandler as anonymous classes. Next, KeyFrame instances are created which take in the EventHandler instances at start and stop durations and are right away added to the animation, i.e., the Timeline instance.EventHandler<ActionEvent> startAudio = new EventHandler<ActionEvent>() { @Override public void handle(ActionEvent arg0) { mediaPlayer.play(); } }; EventHandler<ActionEvent> stopAudio = new EventHandler<ActionEvent>() { @Override public void handle(ActionEvent arg0) { mediaPlayer.stop(); } }; animation.getKeyFrames().add(new KeyFrame(new Duration(0.0), startAudio)); animation.getKeyFrames().add(new KeyFrame(new Duration(5000.0), stopAudio)); animation.play();
Conclusion
The main intention of this post is to show how to synchronize animation and media in JavaFX 2.1, using Timeline, KeyFrame and EventHandler classes. Alongside, a simple animation and the load of an audio file are also described and used as basis to the main subject.
Assinar:
Postagens (Atom)