Countdown

Final Countdown

Faltam dias. Ou segundos.

domingo, 3 de maio de 2015

Projeto Anima

Conclusão do Projeto


Conforme descrito no Plano de Projeto, hoje concluímos com sucesso o Projeto Anima, referente ao jogo de tiro Bizuca. O código completo do projeto e o executável do jogo foram disponibilizados no link abaixo:










Comentários sobre o projeto:


Como principal mudança na versão final do programa temos a criação de uma interface gráfica para o software (GUI - Graphic User Interface). A tarefa transcorreu de forma simples e com poucas modificações do problema, tendo em vista que a implementação do programa considerou desde o início as especificações de uma interface, porém sem se preocupar com ela.

Apenas tivemos de relacionar os elementos de uma interface (botões, abas, elementos de texto) às respectivas funções já bem implementadas até o momento, não sendo necessária quase nenhuma modificação do código.

1) Bizuca.java (Main) - 20 linhas


Classe responsável pela criação do JFrame do jogo. Sem alterações.

2) Fase.java - 55 linhas


Classe responsável pela criação da fase e identificação da região de parede e da região do chão, permitindo o jogador/bots/tiros se locomoverem através do cenário.

3) Figura.java - 170 linhas


Classe responsável pelas figuras e suas propriedades no jogo, como por exemplo os bots e o próprio jogador. Foram adicionadas novas variáveis e funcionalidades, em relação à versão passada.

4) Musica.java - 35 linhas


Essa classe surgiu como uma tentativa de descentralizar o código da classe Game.java, que estava se tornando muito grande. Conforme o desenvolvimento do projeto continue, pode ser interessante fragmentar suas funcionalidades de mouse, inteligência artificial, desenho, etc. Em classes menores e especializadas.

5) Game.java - 500 linhas


É a classe faz tudo do jogo, que acabou centralizando todos os processos por se responsabilizar pela pintura do JPanel onde ocorre o jogo. Neste sentido, acabou se encarregando do controle e do sistema de colisão, até mesmo o controle das inteligências artificiais. Sua novas funcionalidades são listadas abaixo:

[AI - Inteligência Artificial]
Os bots tem autonomia de decisão e bom senso no sentido de melhorar a experiência de jogo. Possuem recursos de visão para detecção do jogador, que engatilha o método responsável pelo tiro. Os bots também detectam paredes, o que provoca uma mudança do seu ângulo de visão e consequente desvio dos obstáculos do cenário.

[TE - Eventos Temporais]
Dentre eles, o aparecimento de munição adicional na fase, morte por limite de tempo e regeneração da vida do jogador ao longo do tempo, tornando o jogo muito mais desafiador.

[Cenário editado]
Melhorias do gráfico do cenário, com mais cores e tornando o ambiente de jogo mais agradável.

[Telas de vitória e derrota]
Agora o jogo conta com telas de vitória e de derrota, permitindo ao jogador ter a experiência completa de um jogo. Recursos auditivos (músicas e sons) também aprimoram o jogo nesta nova versão.


Conclusões:
Apesar das muitas dificuldades encontradas durante o projeto, como a de programação de recursos de imagens em baixo nível, tendo de implementar sistemas de colisão, inteligência artificial para a implementação da visão e a decisão dos bots, calibragem das variáveis para o correto funcionamento do jogo, esforços delongados para otimizar o jogo e deixá-lo mais rápido e compacto, o projeto Anima finalmente encontra o seu fim. Trazemos algumas ideias para a sua melhoria no futuro:

[Ideias para melhoria do software no futuro]:


-> Melhoria da programação, com otimizações do código e do sistema de uso de imagens (Uso de API's específicas para jogos).
-> Melhoria do desempenho do jogo, aumentando sua velocidade e diminuindo seu uso de memória.
-> Aprimoramento da rústica inteligência artificial utilizada, introduzindo fundamentos teóricos em sua criação.
-> Criação de um ambiente de jogo em rede, permitindo a ocorrência de jogos online.

domingo, 26 de abril de 2015

#16) Análise de desempenho no Netbeans

Boa noite. Trabalhando no projeto do jogo de tiro Bizuca, me deparei com um problema sério sobre o qual eu nunca havia pensado em meus projetos anteriores. O problema do desempenho do programa, tanto na velocidade de execução como na demanda de CPU e de memória RAM em sua execução. Hoje venho apresentar um pouco de teoria para analisar o desempenho de um software usando o Netbeans.

Tela de vitória do jogo Bizuca.

A determinação do desempenho relativo ao uso de CPU e uso de memória RAM do software (além da monitoração dos Threads envolvidos no programa) em questão pode ser realizada acessando a ferramenta localizada no menu Perfil do Netbeans (atalho Alt+F2):

Ferramenta de análise de desempenho do Netbeans.

A próxima janela é bem intuitiva, basta selecionar a tarefa de interesse e executá-la. Teste o seu software normalmente, procurando simular uma utilização comum dele.

Análise do Perfil de desempenho do projeto.

No caso de uso da memória RAM, o Netbeans disponibilizará uma grande tabela com o uso de memória de acordo com o tipo de variável. Também pode-se vigiar a utilização de memória enquanto o programa é executado.

Tabela de variáveis - Uso de memória RAM.

O uso de CPU pode ser exibido por Threads, métodos ou por classe, de modo a facilitar a análise dos processos críticos do programa que carecem de otimização. Assim o processo de aprimoramento do programa se torna muito mais direcionado, obtendo-se melhorias com menos tempo e menos modificações de otimização.
Tabela de Threads - Uso da CPU.

Por hoje é só. Fica a excelente dica de ferramenta para a análise de desempenho e otimização do Netbeans.

quarta-feira, 22 de abril de 2015

#15) MIDI player em Java

Hoje venho disponibilizar meu recente aprendizado de uma nova funcionalidade para o meu jogo do projeto Anima, que se trata do uso de música MIDI em uma aplicação java. O formato MIDI trata de músicas puramente instrumentais e digitalizadas, como se fosse a reprodução exata e unívoca de uma partitura. Por isso os arquivos de música .mid ocupam pouco espaço no disco rígido (HD) e são tão comuns na web, de modo que optamos por utilizar esse formato.

Seu uso não mistérios. Usando a biblioteca import javax.sound.midi.*; O carregamento do arquivo midi e sua execução ocorrem de maneira muito similar a de uma imagem, conforme o código exemplo abaixo:


package cs;
 
import javax.sound.midi.*;
import java.io.*;
 
public class Música {
 
    String musica_ = "src\\cs\\imagens\\musica.mid";
    File midiFile = new File(musica_);
 
    public void playMusic() {
        if (!midiFile.exists() || midiFile.isDirectory()
                || !midiFile.canRead()) {
            System.out.println("Argumentos inválidos.");
            System.exit(1);
        }
 
        try {
            Sequencer seq = MidiSystem.getSequencer();
            seq.setSequence(MidiSystem.getSequence(midiFile));
            seq.open();
            seq.start();
 
            while (seq.isRunning()) {
                try {
                    Thread.sleep(1000);
                } catch (InterruptedException ignore) {
                    break;
                }
            }
            seq.stop();
            seq.close();
        } catch (MidiUnavailableException mue) {
            System.out.println("Dispositivo de MIDI indisponível");
        } catch (InvalidMidiDataException imde) {
            System.out.println("Dados MIDI Inválidos");
        } catch (IOException ioe) {
            System.out.println("Erro de I/O");
        }
    }
 
    Música() {
        playMusic();
    }
 
    public static void main(String args[]) {
        new Música();
    }
 
}
 
Aplicação java com uso de arquivo midi.

Assim, concluo o pequeno post de hoje.

sexta-feira, 17 de abril de 2015

#15) Programação gráfica em Java: Desenhos

Hoje venho apresentar os primeiros resultados do jogo de tiro sobre o qual falei no último post, referente ao projeto Bizuca. Vou apresentar a principal ferramenta nativa de Java que utilizei para criar os gráficos e a animação do jogo:

[Bizuca V 1.0]


 ---//---

[Desenhos em Java]

Todo o desenho do projeto foi desenvolvido em cima da classe Graphics, que trabalha no redesenho do JPanel do nosso projeto:
import java.awt.Graphics;

Assim, o método principal de desenho sobre o JPanel é o paintComponent, que recebe um objeto do tipo Graphics. Chamando primeiro o método da superclasse:
super.paintComponent (g);

Assim, um programa básico de desenho, que traçaria, por exemplo, uma linha reta, teria a seguinte estrutura:

Lines.java
import javax.swing.JFrame;
 
public class Lines {
 
    public static void main(String[] args) {
       DrawLines panel = new DrawLines();
 
       JFrame frame= new JFrame("Meu primeiro desenho");
 
        frame.setDefaultCloseOperation( JFrame.EXIT_ON_CLOSE );
        frame.setSize( 250, 250 );
        frame.setVisible( true );
        frame.add( panel );
 
        }
}

DrawLines.java
import java.awt.Graphics;
import javax.swing.JPanel;
 
public class DrawLines extends JPanel{
 
    public void paintComponent( Graphics g ){
    super.paintComponent( g );
 
    g.drawLine( 0, 0, 250, 250 );
 
    }
}

Porém, o grande diferencial desta classe é possibilidade de manipular imagens de diversos formatos (.bmp, .png, etc) com grande facilidade, abrindo um grande leque de possibilidades para a criação de jogos. Para a criação de uma imagem, é preciso usar as seguintes classes:
import java.swing.ImageIcon;
import java.awt.Image;

Abaixo, um exemplo de aplicação com imagens. Note que o caminho da imagem deve ser especificado no código. O ideal é criar um pacote no projeto para colocar as imagens, que podem ser inseridas simplesmente arrastando-as para dentro do pacote, conforme a imagem abaixo:
Figura 1 - Projeto com Imagens

Assim, temos um exemplo de projeto com imagens:

Figura.java
package figura;
 
import javax.swing.JFrame;
 
public class Figura {
 
    public static void main(String[] args) {
        Panel panel = new Panel();
 
        JFrame frame = new JFrame("Meu primeiro desenho");
 
        frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
        frame.setSize(450, 450);
        frame.setVisible(true);
        frame.add(panel);
 
    }
}
Panel.java
package figura;
 
import java.awt.Color;
import java.awt.Graphics;
import java.awt.Image;
import javax.swing.ImageIcon;
import javax.swing.JPanel;
 
public class Panel extends JPanel {
    Image imagem;
    ImageIcon icon;
    String caminho = "src\\imagens\\pentagrama.png";
 
    public void paintComponent(Graphics g) {
        super.paintComponent(g);
 
        icon = new ImageIcon(caminho);
        imagem = icon.getImage();
 
        g.drawImage(imagem, 10, 10, this);
        g.setColor(Color.red); g.drawLine(0, 0, 350, 350);
 
    }
}

O resultado terá a seguinte forma:
Figura 2 - Resultado da aplicação com uso de imagem.

E assim concluo a apresentação deste recurso interessante e poderoso. Deixo o link para um site bem didático que ensina a criação de um game clássico de naves e tiros:

E ainda mais alguns links:

sexta-feira, 10 de abril de 2015

#14) Estrutura de um Jogo & Multithreading

Olá, hoje venho aqui apresentar a segunda proposta de projeto do curso, o Projeto Anima. Nosso projeto se chamará Bizuca um jogo de tiro em 2D com programação gráfica em Java, contando com o uso de inteligência artificial (Bots).

 ---//---

[Estrutura de um Jogo]

Primeiramente, é preciso estruturar o esqueleto do jogo, enumerando os seus principais recursos e funcionalidades que irão garantir o seu funcionamento, conforme o esquema abaixo:
 
 -------------------------------------------\\-----------------------------------------------
{Menu que antecede o início do jogo}
: Início do Jogo :

-> Setar valores iniciais
(Carregar cenário, configurações iniciais)
-> Loop principal 
   {
      -> Redesenho  da Tela

       -> Ciclo de Animações

      -> Decisões do Jogador  [ Comandos (Mouse, Teclado) ]

      -> Decisões da AI

      -> Processamento
      (Checa colisões e consequências das decisões)

      -> Comando de espera


   }

: Fim do Jogo : 
-------------------------------------------\\-----------------------------------------------

Cada funcionalidade do jogo pode vir na forma de um método relacionado a uma Classe do projeto, deixando o código mais limpo e organizado.
 Entretanto, checar todas as colisões do jogo, com diversos bots (AI's), jogadores, itens dos cenários e objetos extras (como por exemplo tiros) pode tornar o processo lento, sendo necessário para isso o uso de Threads.

 ---//---
 
[Uso do Multithreading]


Usado para processos "simultâneos" executados em paralelo, prevenindo, por exemplo, que a tela congele enquanto uma tarefa que demanda tempo está executando.
Diferente da linguagem C/C++, Java possui suporte nativo a multithreading, facilitando o seu uso. Java Thread é um processo criado pela Máquina Virtual Java:

Runnable: Interface que representa algo que pode ser executado em um Thread.


Thread: Classe que executa a implementação de Runnable em processo paralelo.




-------------------------------------------\\-----------------------------------------------

public class CounterPrinter extends Thread {
public void run () {
for(int i=0; i<10; i++)
System.out.println(i);
}
}

CounterPrinter p = new CounterPrinter();
p.start();


-------------------------------------------\\-----------------------------------------------
Código 1 - Uso de Thread.

Um processo Thread possui diversos estados. Ele pode estar em execução, em estado de Espera, Sleep, Bloqueio, Terminado, etc. Dentre os Threads de Java, existem 10 níveis de prioridade.


Figura 1 - Estados de um Thread Java.


Sleep: Thread.sleep ( SleepTime );
Usado para que o Thread pause por um certo período de tempo.

Método synchronized:
Métodos desse tipo usam a instância como um semáforo, permitindo somente o processamento do Thread somente se este receber o devido "Sinal Verde".

Wait: Thread.wait ();
Força a suspensão do Thread liberando o acesso a outro Thread.

Notify: Thread.notify ();
Acorda uma Thread suspensa no objeto.



No caso deste projeto, usaremos a funcionalidade para:

-> Checar todas as colisões, cada uma com um Thread distinto, agilizando muito a velocidade de processamento, sendo que cada um é colocado para dormir após terminar a sua tarefa. Para checar a colisão novamente, basta acordar todos os Threads que estavam anteriormente dormindo.

-> Tomar todas as decisões das AI's simultaneamente, a análise demorada Ordem N (N AI's) se torna Ordem 1, agilizando o jogo e melhorando a experiência do jogador. 

-> Comando de espera para recomeçar o Loop dos eventos do jogo.

quarta-feira, 8 de abril de 2015

#13) Criação de um Applet

[Applets]

Um Applet é um programa em Java que é executado em um Web Browser. Um Applet conta com as mesmas funcionalidades de uma aplicação Java, com algumas diferenças:
  • O método Main não é chamado no Applet, uma classe Applet não faz uso da Main.
  • Applet usualmente são incorporados em uma página HTML.
  • Um Apllet é uma classe Java que estende a classe java.applet.Applet.
  • A aplicação é exibida de forma semelhante a uma imagem em um Applet.
O Applet pode ser criado com auxílio do NetBeans, para aplicações contendo ou não GUI:



1. Aplicação sem GUI:

Criar um novo projeto no NetBeans normalmente, uma nova classe (sem o método Main) e então usar os comandos desejados, como por exemplo o projeto MyApplet.java abaixo:

-------------------------------------------\\-----------------------------------------------
package applet;

import java.applet.Applet;
import java.awt.Graphics;

public class MyApplet extends Applet {
    @Override
    public void paint(Graphics g) {
        g.drawString("Hello Worldt!", 50, 25);
    }

}
-------------------------------------------\\-----------------------------------------------
Código 1 - Superclasse Shapes.

@Override significa que a função paint(...) já existe na classe Applet, no entando, como a classe MyApplets é subclasse de Applet, ela pode conter uma função de mesmo nome substituindo a função herdada de sua Superclasse.
A função paint(...) é chamada sempre que alguma alteração do Applet ocorre, sendo necessário imprimi-lo novamente na tela do Browser. Neste caso, desejamos imprimir uma mensagem HelloWorld na tela do navegador.

Para executar o arquivo, vá na aba Executar do NetBeans e selecione "Executar Arquivo (Shift+F6)". O visualizador de Applets será exibido:


Figura 1 - Funcionamento do Applet.

Acessando a pasta dos arquivos do projeto, note que surgirá um arquivo .html após o Build (construção do arquivo executável do projeto). Experimente clicar no arquivo para examinar o seu código (em HTML -  ver a referência de sites se quiser aprofundar no assunto):

Figura 2 - Arquivo HTML gerado.

Figura 3 - Código do arquivo HTML do Applet.

Seria interessante executar o Applet diretamente do arquivo HTML. Foi o que tentei fazer logo em seguida, entretanto, por restrições de segurança do Java após certa atualização, a aplicação foi barrada no Browser: 
Os Applets foram planejados para serem carregados de um site remoto e então executados localmente, no sistema do usuário. Para evitar que este sistema seja danificado por pessoas mal intencionadas, as aplicações são monitoradas pelo Applet security manager, é comum dizer que os Applets atuam em uma caixa de areia, um modelo conhecido como the sandbox model, restringindo seu alvo de atuação.
Figura 4 - Erro gerado pela falha de segurança do Applet.

Após rápida pesquisa na web, entendi que o Applet deve gerar uma auto-assinatura para evitar que o programa realize operações de risco no sistema local do usuário, por exemplo. Não consegui, contudo, encontrar um método simples e funcional para corrigir a falha, de forma que deixarei a tarefa para um post futuro.

Antes de explorar mais a fundo os comandos, vamos abordara criação de Apllets com GUI (interface gráfica).

2. Aplicação com GUI:

A aplicação com GUI é um pouco mais simples de ser implementada. Basta:

  1. Criar novo projeto
  2. Clique da direita no pacote do projeto
  3. Selecionar "Novo" e então "Outros"
  4. Em "Categorias", selecione "Forms GUI Swing" e então "Form JApplet".
Figura 5 - JApplet com GUI.

Pronto! Agora você deverá visualizar o ambiente de trabalho do NetBeans apresentado em posts passados, com a diferença que agora se trata de um Applet. Executando o arquivo (Shift+F6) você deverá ver o familiar Visualizador de Applets.

Figura 6 - Visualizador de Applet.