segunda-feira, 24 de junho de 2013

[Tutorial] [Video] [Illustrator] Desenhos em Pixel-Art

Olá pessoal! Neste tutorial vou ensinar como fazer uma arte um tanto diferente, uma pixel-art! Com este tipo de art você desenha com pixels, que permite os seus desenho parecerem imagens de 8-bits, muitos de vocês podem utilizar esse tutorial, somente para fazer suas artes ou ainda criar os sprites dos seus games, que ensino a fazer aqui no blog! Mas enfim, vamos lá, inicialmente para quem não entendeu nada do que eu to falando, vou mostrar abaixo uma pixel-art que desenvolvi.


TCHAAAAAAAARÃN! Se você percebeu que é o Superman e o Batman, fiz um bom trabalho ( HUAHAHUHA, por mais que tenha ficado péssimo o trabalho, impossível não perceber, mas enfim ). Essa pixel-art faremos no Illustrator, para quem não tiver esse programa, não se preocupe, pretendo realizar esse tutorial no Photoshop, e até mesmo no Paint. As ferramentas que vamos utilizar nesse tutorial é Rectangular Grid Tool ( para fazer nossos "pixels" ), Live Paint Bucket ( para pintar os pixels ) e Eyedrooper Tool ( o conta gostas ). Mas já falei demais................ vamos ao vídeo-tutorial! Primeiro a imagem que usei neste tutorial.


SIIIIIIM, é o Mordecai de Apenas um Show (Regular Show), se você não conhece não vive a infância de agora ( HUAHUAHU isso porque já sou velho ). Mas enfim, agora com essa imagem, vejamos o video!



WOW, não sei se o video ficou bom, mas enfim, o resultado, aqui, agora, JÁ!


O que acharam?? Bom pessoal é isso ai, libertem sua criatividade! Até a próxima!

sexta-feira, 21 de junho de 2013

[Blog] Redes Sociais

Olá pessoal que acompanha o blog, um informe rapidinho, estão liberadas, nossas três redes sociais, WOOOOOOOOW demorou mas estamos juntos. Curtam, compartilhem, sigam, inscrevam-se e sejam felizes!

FACEBOOK: 
TWITTER: https://twitter.com/itscaiqueck
YOUTUBE: http://www.youtube.com/user/8itoporcento

quinta-feira, 20 de junho de 2013

[Tutorial] [Java] PAC-MAN - Preparação

Olá pessoal! Aqui estamos com mais um inicio de tutorial ( esse pelo jeito vai ser muuuuuuuuito MUITOOOOO longo ), aqui vamos desenvolver um jogo completo do personagem PAC-MAN, com tudo, TUDO que temos direto no jogo ( hehehe completíssimo ). Como eu nunca vi esse material na internet, vou auxiliar vocês a conhecer um jogo por completo. É uma base para continuar o jogo de plataforma ( que conta com colisões, gravidades, vetores, etc.... ). Inicialmente, na preparação, vamos observar o principio do jogo. Observem abaixo.

PERSONALIDADE DO PACMAN NO JOGO

Anda para todas as direções, come as comidas, tem a cereja, e ainda as pílulas de poder. Necessita comer todos itens na tela para passar de nível, ganha um score diferente para cada item coletado.

PERSONALIDADE DE CADA FANTASMA DO JOGO

Blinky (Vermelho) – É o Boss principal do jogo que constrói maior dificuldade, começa o nível em uma velocidade constante igual dos outros fantasmas do jogo, porém após você devorar certa quantidade de comida, ele começa a aumentar sua velocidade. Anda no jogo pelo sentido horário. Sempre escolhe o caminho mais curto.

Pinky (Rosa) – É (quase) sempre o primeiro que sai do jogo depois do Blinky. Anda no jogo pelo sentido anti-horário. Sempre mantém sua aceleração.

Inky (Azul) – Perigoso e imprevisível. Diferentes voltas em tempos diferentes. É controlado com a proximidade do Blinky. Percorre o caminho mais longo. Considerado meio anti-social.

Clyde (Laranja) – O mais lerdo e desatento.

Temporariamente os fantasmas se desligam, e vão para suas casas (quatro cantos do jogo), até que persigam novamente o Pacman, as vezes nem dá tempo de eles chegarem em casa. Desligam-se somente 4 vezes para cada vida, e nível do jogo. Os fantasmas saem da casa central em modo de desligamento. O ciclo dos fantasmas é:

Ao iniciar o jogo: 7 segundos desligados, 20 segundos atacando, 7 segundos desligados, 20 segundos atacando, 5 segundos desligados, 20 segundos atacando, 5 segundos dormindo, atacando até o reiniciamento.

Se o Blinky entrar no modo de aceleração ele não desligara mais, e será aleatoriamente desligado. Se o Pacman comer a pílula de poder, os fantasmas entram no modo azul, e o modo de desligamento é pausado, todos fantasmas ficam lentos. Ao acabar o poder, eles retornam para onde estavam e a contagem continua.

RASCUNHO DE LÓGICA

PACMAN
> Andar sobre a tela
> Verificar colisão com o Tile (Mapa do Jogo); com a comida; com a pílula de poder; com a cereja.

FANTASMAS
> Traçar e percorrer o caminho para encontrar o Pacman no jogo, conforme sua personalidade (PathFinder).
> Verificar colisão com o Pacman, e o Tile.
> Controlador de tempo.
> Mudança para o modo azul.

TILE MAP
> Conter comidas, cerejas, e blocos de colisão.

DESENHO
> Controlar desenhos do jogo, e suas posições (x,y) assim como suas distâncias.

ANIMAÇÃO
> Controlar a animação dos sprites.

COMUNS
> Definir variáveis globais.

NÍVEL
> Representar o nível do jogo.

MENU
> Controla menus do jogo.

VECTOR2

> Uma classe auxiliar para manipular facilmente o plano (x,y).

GRADE

> Controla o ambiente do jogo.




E é isso aí!!!!!! Agora com nosso esquema, na parte 1 do tutorial ( lançada no sábado, provavelmente ) será criada a classe Desenho, Comuns, Menu, Vector2 e Grade ( parcialmente, nesse tutorial iremos testar o funcionamento de cada parte ). Até lá ;)

domingo, 16 de junho de 2013

[Tutorial] [Java] Jogo Invasores do Espaço - Parte 2

Hello people! Aqui estamos com a parte 2 de criação do nosso mini-jogo estilo Atari ( hehehe ). Nesta parte, vamos abordar duas classes, a principal e a Grade do jogo, a gigante, a enorme, a complexa! Acompanhem com calma que no fundo é bem fácil.

InvasoresDoEspaco (principal, JFrame) - Exibe o jogo na tela
Grade (JPanel) - Controla todos processos do jogo

CLASSE GRADE

A classe GRADE, é a principal do jogo, que manipula todos gráficos na tela, assim como toda interação entre os objetos, eu poderia fazer um texto gigante para explicar ela inteira, mas o código já é maior ainda, e tem muitos comentários, então aproveitem todo código.

package INVASORESDOESPACO;

// Importações necessárias para a classe
import java.awt.Color;
import java.awt.Dimension;
import java.awt.Font;
import java.awt.FontMetrics;
import java.awt.Graphics;
import java.awt.Toolkit;
import java.awt.event.KeyAdapter;
import java.awt.event.KeyEvent;

import java.util.ArrayList;
import java.util.Iterator;
import java.util.Random;

import javax.swing.ImageIcon;
import javax.swing.JPanel;

/*
 *
 * AUTOR: CAIQUE MONTEIRO ARAUJO
 * DATA: 09/06/2013
 * CLASSE: GRADE
 * OBJETIVO: AMBIENTE DO JOGO
 *
 */

// EXTENDE A CLASSE AOS ATRIBUTOS E MÉTODOS DA CLASSE JPANEL
// IMPLEMENTA A PROCESSO DE EXECUÇÃO E A CLASSE COMUNS
public class Grade extends JPanel implements Runnable, Comuns
{

    // DEFINE A DIMENSÃO DO AMBIENTE
    private Dimension dimensão;

    // CRIA UMA ARRAY COM OS ALIENS DO JOGO
    private ArrayList aliens;
    // CRIA UM JOGADOR PARA O JOGO
    private Jogador jogador;
    // CRIA UM TIRO PARA O JOGADOR
    private Tiro tiro;

    // DEFINE AS POSIÇÕES DE (x,y) PARA O ALIEN
    private int alienX = 150;
    private int alienY = 5;

    // DEFINE A DIREÇÃO DO MOVIMENTO PADRÃO
    private int direção = -1;
    // DEFINE A QUANTIDADE DE MORTES DOS ALIENS
    private int mortes = 0;
    // DEFINE A QUANTIDADE DE VIDAS DO JOGADOR
    private int vidas = 3;

    // VALIDA QUE O JOGO ESTÁ EM EXECUÇÃO
    private boolean estaJogando = true;

    // DEFINE A IMAGEM PARA A EXPLOSÃO
    private final String explosao = "explosão.png";
    // DEFINE A IMAGEM PARA OS ALIENS
    private final String alienimg = "alien.png";

    // MENSAGEM DO JOGO
    private String mensagem = "FIM DE JOGO!";

    // THREAD PARA ANIMAR O JOGO
    private Thread animador;

    // MÉTODO CONSTRUTOR DA CLASSE
    public Grade ()
    {
        // POSSIBILIDADE DE INTERAÇÃO COM O TECLADO
        addKeyListener(new TAdapter());

        // DEFINE O FOCO PARA ESSE JPANEL
        setFocusable(true);
        // DEFINE SUA DIMENSÃO
        dimensão = new Dimension(LARGURA, ALTURA);
        // SETA A COR DO PLANO DE FUNDO
        setBackground(Color.BLACK);

        // INICIA O JOGO
        initJogo();
    }

    // CONTROLA AS NOTIFICAÇÕES DO THREAD
    @Override
    public void addNotify()
    {
        // DEFINE ESTE COMO ELE MESMO
        super.addNotify();
        // INICIA O JOGO
        initJogo();
    }

    // MÉTODO PARA INICIAR O JOGO
    public void initJogo ()
    {
        // CRIA UMA NOVA LISTA DE ALIENS
        aliens = new ArrayList();

        // CARREGA A IMAGEM DO ALIEN
        ImageIcon alien_ = new ImageIcon(alienimg);

        // MAPA DE ALIENS, DISPOSTOS EM 4 LINHAS X 6 COLUNAS
        for (int i = 0; i < 4; i++)
        {
            for (int j = 0; j < 6; j++)
            {
                // CRIA UM NOVO ALIEN PASSANDO COMO PARÂMETOS SUAS POSIÇÕES NA TELA
                Alieniginas alien = new Alieniginas(alienX + 18*j, alienY + 18*i);
                // SETA A IMAGEM DO ALIEN CRIADO
                alien.setImagem(alien_.getImage());
                // ADICIONA O ALIEN NA ARRAY DO JOGO
                aliens.add(alien);
            }
        }

        // CRIA UM NOVO JOGADOR
        jogador = new Jogador();
        // CRIA UM NOVO TIRO
        tiro = new Tiro();

        // SE O THREAD ESTIVER NULL, OU O JOGO NÃO ESTIVER RODANDO
        if (animador == null || !estaJogando)
        {
            // INSTÂNCIA PARA O THREAD ESTA CLASSE
            animador = new Thread(this);
            // INICIA A EXECUÇÃO DO THREAD
            animador.start();
        }
        
    }

    // MÉTODO PARA DESENHAR ALIENS NA TELA
    public void desenharAliens (Graphics g)
    {
        // CRIA UM CURSOR DE POSICIONAMENTO NA ARRAY DOS ALIENS
        Iterator it = aliens.iterator();

        // ENQUANDO EXISTIR UM PRÓXIMO CURSOR, CAPTURA UM ALIEN DA ARRAY,
        // SE ESTE ALIEN ESTIVER VISÍVEL ENTÃO DESENHA ELE NA TELA, COM SUA
        // POSIÇÃO (x,y), SE ELE ESTIVER MORRENDO ENTÃO MATA O ALIEN NA TELA
        while (it.hasNext())
        {
            Alieniginas alien = (Alieniginas) it.next();

            if (alien.isVisivel())
            { g.drawImage(alien.getImagem(), alien.getX(), alien.getY(), this); }

            if (alien.isMorrendo()) 
            { alien.morrer(); }
        }
    }

    // MÉTODO PARA DESENHAR JOGADOR NA TELA
    public void desenharJogador (Graphics g)
    {
        // SE O JOGADOR ESTIVER VISÍVEL ENTÃO DESENHA ELE NA TELA, COM SUA
        // POSIÇÃO (x,y), SE ELE ESTIVER MORRENDO ENTÃO MATA O JOGADOR NA TELA
        // E FINALIZA O JOGO

        if (jogador.isVisivel())
        { g.drawImage(jogador.getImagem(), jogador.getX(), jogador.getY(), this); }

        if (jogador.isMorrendo())
        { jogador.morrer(); estaJogando = false; }
    }

    // MÉTODO PARA DESENHAR TIRO NA TELA
    public void desenharTiro (Graphics g)
    {
        // SE O TIRO ESTIVER VISÍVEL ENTÃO DESENHA ELE NA TELA, COM SUA
        // POSIÇÃO (x,y)
        if (tiro.isVisivel())
        { g.drawImage(tiro.getImagem(), tiro.getX(), tiro.getY(), this); }
    }

    // MÉTODO PARA DESENHAR BOMBA NA TELA
    public void desenharBomba (Graphics g)
    {
        // CRIA UM CURSOR DE POSICIONAMENTO NA ARRAY DOS ALIENS
        Iterator it = aliens.iterator();

        // ENQUANDO EXISTIR UM PRÓXIMO CURSOR, CAPTURA UM ALIEN DA ARRAY,
        // E OBTEM A BOMBA DESSE ALIEN, SE A BOMBA NÃO ESTÁ DESTRUIDA
        // ENTÃO DESENHA ELA NA TELA COM SUAS POSIÇÕES (x,y)
        while (it.hasNext())
        {
            Alieniginas alien = (Alieniginas) it.next();

            Alieniginas.Bomba bomba = alien.getBomba();

            if (!bomba.isDestruido()) 
            { g.drawImage(bomba.getImagem(), bomba.getX(), bomba.getY(), this); }
        }
    }

    // MÉTODO PARA DESENHAR A PONTUAÇÃO NA TELA
    public void desenharScore (Graphics g)
    {
        // DEFINE A STRING DE EXIBIÇÃO
        String score = "Pontuação: " + mortes;

        // CRIA UM ESTILO DE FONTE
        Font estilo = new Font("Consolas", Font.BOLD, 12);

        // SETA A COR DA FONTE
        g.setColor(Color.white);
        // SETA O ESTILO DE FONTE
        g.setFont(estilo);
        // DESENHA A STRING COM A POSIÇÃO (x,y)
        g.drawString(score, 10, 20);
    }

    // MÉTODO PARA DESENHAR VIDAS NA TELA
    public void desenharVidas (Graphics g)
    {
        // DEFINE A STRING DE EXIBIÇÃO
        String vida = "VIDAS";
        // CRIA UM ESTILO DE FONTE
        Font estilo = new Font("Consolas", Font.BOLD, 12);
        // CRIA A MÉTRICA DA FONTE
        FontMetrics metrica = this.getFontMetrics(estilo);

        // OBTÉM O TAMANHO DA STRING NA TELA
        int width = metrica.stringWidth(vida);
        // CALCUPA A DISTÂNCIA DA BORDA PARA POSICIONAR A STRING
        int distancia = (15 * vidas) + (5 * vidas) + 25 + width;

        // PARA CADA VIDA DO JOGADOR, DESENHA UMA IMAGEM DA VIDA,
        // ALTERANDO A POSIÇÃO COM BASE NOS CALCULOS PARA DEFINIR
        // A POSIÇÃO DE CADA UMA EM (x,y)
        for (int i = 0; i < vidas; i++)
        {
            g.drawImage(jogador.getImagem(), LARGURA - width, 10, this);
            width += JOGADOR_WIDTH + 5;
        }

        // SETA A COR DA FONTE
        g.setColor(Color.white);
        // SETA O ESTILO DE FONTE
        g.setFont(estilo);
        // DESENHA A STRING COM A POSIÇÃO (x,y)
        g.drawString(vida, LARGURA - distancia, 20);
    }

    // MÉTODO PARA DESENHAR NA TELA COM ATUALIZAÇÃO
    @Override
    public void paint (Graphics g)
    {
        // DEFINE O PAINT COMO ELE MESMO
        super.paint(g);

        // SETA UMA COR
        g.setColor(Color.black);
        // DESENHA UM RETÂNGULO DO TAMANHO DA TELA
        g.fillRect(0, 0, dimensão.width, dimensão.height);
        // SETA UMA COR
        g.setColor(Color.green);

        if (estaJogando)
        {
            // DESENHA UMA LINHA PARA REPRESENTAR A BASE
            g.drawLine(0, BASE, LARGURA, BASE);
            // DESENHA TODOS OBJETOS DO JOGO CHAMANDO OS MÉTODOS CRIADOS
            // ANTERIORMENTE
            desenharAliens(g);
            desenharJogador(g);
            desenharTiro(g);
            desenharBomba(g);
            desenharVidas(g);
            desenharScore(g);
        }

        // ATIVA A SINCRONIA
        Toolkit.getDefaultToolkit().sync();
        // PAUSA
        g.dispose();
    }

    // DEFINE O CICLO DE ANIMAÇÃO E EXECUÇÃO DO JOGO NA TELA
    public void cicloAnimacao()
    {
        // VERIFICA SE JÁ MORRERAM TODOS OS ALIENS, CASO ISSO TENHA ACONTECIDO
        // PARA O JOGO, E DEFINE A MENSAGEM
        if (mortes == NUMERO_DE_ALIENS)
        {
            estaJogando = false;
            mensagem = "VOCÊ VENCEU!";
        }

        // JOGADOR COMEÇA A OPERAR
        jogador.atuar();

        // CONTROLA O TIRO SE ESTE ESTIVER VISÍVEL
        if (tiro.isVisivel())
        {
            // CRIA UM CURSOR DE POSICIONAMENTO NA ARRAY DOS ALIENS
            Iterator it = aliens.iterator();

            // OBTEM AS POSIÇÕES (x,y) DO TIRO
            int tiroX = tiro.getX();
            int tiroY = tiro.getY();

            // ENQUANTO O EXISTIR UM PRÓXIMO CURSOR, ELE CAPTURA UM ALIEN
            // DA ARRAY, RESGATA SEU POSICIONAMENTO EM (x,y) VERIFICA SE
            // O ALIEN ESTÁ VISÍVEL E O TIRO TAMBÉM, SE ESTIVER VERIFICA SE
            // O TIRO ATINGIU O ALIEN CAPTURADO, CASO ISSO ACONTEÇA, DEFINE
            // UMA NOVA IMAGEM PARA O ALIEN, INFORMA QUE O ALIEN ESTÁ MORRENDO,
            // ACRESCENTA UMA MORTE NO JOGO, E TERMINA O TIRO
            while (it.hasNext())
            {
                Alieniginas alien = (Alieniginas) it.next();

                int alienX_ = alien.getX();
                int alienY_ = alien.getY();

                if (alien.isVisivel() && tiro.isVisivel())
                {
                    if (tiroX >= alienX_ &&
                        tiroX <= (alienX_ + ALIEN_WIDTH) &&
                        tiroY >= alienY_ &&
                        tiroY <= (alienY_ + ALIEN_HEIGHT))
                    {
                        ImageIcon explosao_ = new ImageIcon(explosao);
                        alien.setImagem(explosao_.getImage());
                        alien.setMorrendo(true);
                        mortes++;
                        tiro.morrer();
                    }
                }
            }

            // PERCORRE O TIRO NO EIXO Y PARA CIMA, CASO O TIRO SAIA DA TELA
            // TERMINA O TIRO, CASO CONTRÁRIO CONTINUA SUBINDO
            int y = tiro.getY();
            y -= 4;
            
            if (y < 0)
            { tiro.morrer(); }
            else
            { tiro.setY(y); }
        }

        // CONTROLE DE ALIENIGINAS
        // CRIA UM CURSOR DE POSICIONAMENTO NA ARRAY DOS ALIENS
        Iterator itAlien = aliens.iterator();

        // ENQUANTO O EXISTIR UM PRÓXIMO CURSOR
        while (itAlien.hasNext())
        {
            // CAPTURA UM ALIEN E OBTEM SEU POSICIONAMENTO EM X
            Alieniginas alien1 = (Alieniginas) itAlien.next();
            int x = alien1.getX();

            // SE A DIREÇÃO FOR PARA DIREITA E ULTRAPASSAR A BORDA
            // INVERTE A DIREÇÃO PARA ESQUERDA, CRIA UM NOVO CURSOR,
            // E ENQUANTO EXISTIREM ALIENS DESCE A POSIÇÃO EM Y
            if (x >= LARGURA - BORDA_DIREITA && direção != -1)
{
                direção = -1;

                Iterator itAlienAux = aliens.iterator();

                while (itAlienAux.hasNext())
                {
                    Alieniginas alien2 = (Alieniginas) itAlienAux.next();
                    alien2.setY(alien2.getY() + VAI_ABAIXO);
                }

            }

            // SE A DIREÇÃO FOR PARA ESQUERDA E ULTRAPASSAR A BORDA
            // INVERTE A DIREÇÃO PARA DIREITA, CRIA UM NOVO CURSOR,
            // E ENQUANTO EXISTIREM ALIENS DESCE A POSIÇÃO EM Y
            if (x <= BORDA_ESQUERDA && direção != 1)
            {
                direção = 1;

                Iterator itAlienAux = aliens.iterator();

                while (itAlienAux.hasNext())
                {
                    Alieniginas alien = (Alieniginas) itAlienAux.next();
                    alien.setY(alien.getY() + VAI_ABAIXO);
                }
            }
        }

        // CRIA UM CURSOR DE POSICIONAMENTO NA ARRAY DOS ALIENS
        Iterator itAliensAux2 = aliens.iterator();

        // ENQUANTO O EXISTIR UM PRÓXIMO CURSOR, CAPTURA UM ALIEN DA ARRAY
        // OBTEM SUA POSIÇÃO EM Y, SE ELE CHEGAR NA BASE, É FIM DE JOGO POR
        // INVASÃO DOS ALIENS. E TAMBÉM ATUA O ALIEN NA POSIÇÃO X COM BASE
        // NA DIREÇÃO
        while (itAliensAux2.hasNext())
        {
            Alieniginas alien = (Alieniginas) itAliensAux2.next();
            if (alien.isVisivel())
            {
                int y = alien.getY();

                if (y > BASE - ALIEN_HEIGHT)
                {
                    estaJogando = false;
                    mensagem = "INVASÃO!";
                }

                alien.atuarX(direção);
            }
        }

        // CONTROLE DE BOMBAS
        // CRIA UM CURSOR DE POSICIONAMENTO NA ARRAY DOS ALIENS PARA BOMBAS
        Iterator itBomba = aliens.iterator();
        // CRIA UM RANDOM
        Random random = new Random();

        // ENQUANTO O EXISTIR UM PRÓXIMO CURSOR
        while (itBomba.hasNext())
        {
            // ESTABELECE UM VALOR ALEATÓRIO PARA ATIRAR A BOMBA
            int tiro_ = random.nextInt(15);

            // CAPTURA UM ALIEN DA ARRAY
            Alieniginas alien = (Alieniginas) itBomba.next();
            // CAPTURA A BOMBA PARA ESTE ALIEN
            Alieniginas.Bomba bomba_ = alien.getBomba();

            // SE O TIRO FOR IGUAL A CHANCES DE ACERTAR, E O ALIEN ESTIVER VISÍVEL
            // E A ULTIMA BOMBA ESTIVER DESTRUIDA, ENTÃO DISPARA OUTRA BOMBA, NA
            // POSIÇÃO (x,y) DO ALIEN
            if (tiro_ == CHANCES && alien.isVisivel() && bomba_.isDestruido())
            {
                bomba_.setDestruido(false);
                bomba_.setX(alien.getX());
                bomba_.setY(alien.getY());
            }

            // OBTEM AS POSIÇÕES DA BOMBA
            int bombaX = bomba_.getX();
            int bombaY = bomba_.getY();

            // OBTEM AS POSIÇÕES DO JOGADOR
            int jogadorX = jogador.getX();
            int jogadorY = jogador.getY();

            // SE O JOGADOR ESTIVER VISÍVEL E A BOMBA NÃO ESTIVER DESTRUIDA,
            // ENTÃO VERIFICA SE A BOMBA ATINGIU A POSIÇÃO DO JOGADOR EM ALGUM
            // PONTO (x,y), SE FOR VÁLIDO, VERIFICA SE A QUANTIDADE DE VIDAS É 1
            // SE FOR, DEFINE COMO MORTE PARA O JOGADOR E DESTRUIÇÃO PARA BOMBA,
            // CASO CONTRÁRIO DESTRÓI A BOMBA, E TIRA UMA VIDA DO JOGADOR
            if (jogador.isVisivel() && !bomba_.isDestruido())
            {
                if (bombaX >= (jogadorX) &&
                    bombaX <= (jogadorX + JOGADOR_WIDTH) &&
                    bombaY >= (jogadorY) &&
                    bombaY <= (jogadorY + JOGADOR_HEIGHT))
                {
                    if (vidas == 1)
                    {
                        ImageIcon explosao_ = new ImageIcon(explosao);

                        jogador.setImagem(explosao_.getImage());
                        jogador.setMorrendo(true);
                        
                        bomba_.setDestruido(true);
                    }
                    else
                    {
                        bomba_.setDestruido(true);
                        vidas--;
                    }
                }
            }

            // SE A BOMBA NÃO ESTIVER DESTRUIDA DESCE ELA NO PONTO Y
            // SE ELA ATINGIR SOMENTE A BASE, SETA ELA COMO DESTRUIDA
            if (!bomba_.isDestruido())
            {
                bomba_.setY(bomba_.getY() + 1);

                if (bomba_.getY() >= BASE - BOMBA_HEIGHT)
                { bomba_.setDestruido(true); }
            }
        }
    }

    // MÉTODO DE EXECUÇÃO DA CLASSE
    public void run ()
    {
        // DEFINE OS CONTROLES DE TEMPO
        long antesTempo, tempoDiferente, sleep;

        // OBTEM O TEMPO ATUAL
        antesTempo = System.currentTimeMillis();

        // ENQUANTO O JOGO ESTIVER EM OPERAÇÃO
        while (estaJogando)
        {
            // REDESENHA A TELA
            repaint();

            // OPERA AS ANIMAÇÕES
            cicloAnimacao();

            // DEFINE UM O TEMPO ATUAL EM RELAÇÃO AO ANTERIOR
            tempoDiferente = System.currentTimeMillis() - antesTempo;
            // APLICA UM DELAY
            sleep = DELAY - tempoDiferente;

            // NÃO DEIXA ELE SEM DORMIR
            if (sleep < 0)
            { sleep = 2; }

            try
            {
                // TENTA FAZER O THREAD DORMIR
                Thread.sleep(sleep);
            }
            catch (InterruptedException e)
            {
                System.out.println("Erro de interrupção!");
            }

            // DEFINE O NOVO TEMPO
            antesTempo = System.currentTimeMillis();
        }

        // MOSTRA A MENSAGEM DE FIM DE JOGO
        FimDeJogo();
    }

    // MÉTODO PARA DESENHAR A MENSAGEM NA TELA
    public void FimDeJogo ()
    {
        // OBTEM OS GRÁFICOS DA TELA
        Graphics g = this.getGraphics();

        // SETA UMA COR
        g.setColor(Color.black);
        // CRIA UM RETANGULO
        g.fillRect(0, 0, LARGURA, ALTURA);

        // SETA A COR
        g.setColor(new Color(0, 32, 48));
        // DEFINE UM NOVO RETANGULO
        g.fillRect(50, LARGURA/2 - 30, LARGURA-100, 50);
        // SETA A COR
        g.setColor(Color.white);
        // DEFINE UM NOVO RETANGULO
        g.drawRect(50, LARGURA/2 - 30, LARGURA-100, 50);

        // DEFINE O ESTILO DA FONTE
        Font estilo = new Font("Consolas", Font.BOLD, 14);
        // DEFINE A MÉTRICA DA FONTE
        FontMetrics metrica = this.getFontMetrics(estilo);

        // SETA UMA COR
        g.setColor(Color.white);
        // SETA UM ESTILO DA FONTE
        g.setFont(estilo);
        // DESENHA A MENSAGEM NA TELA
        g.drawString(mensagem, (LARGURA - metrica.stringWidth(mensagem))/2, LARGURA/2);
    }

    // CRIA UMA CLASSE DE CAPTURA DO TECLADOR
    private class TAdapter extends KeyAdapter {

        // DISPARA O MÉTODO DE SOLTA DE TECLA DO JOGADOR
        @Override
        public void keyReleased(KeyEvent e)
        {
            jogador.keyReleased(e);
        }

        // DEFINE O MÉTODO DE TECLA PRESSIONADA DO JOGADOR
        @Override
        public void keyPressed(KeyEvent e)
        {
            // O JOGADOR SE MOVIMENTA
            jogador.keyPressed(e);

            // CAPTURA SUA POSIÇÃO (x,y)
            int x = jogador.getX();
            int y = jogador.getY();

            // SE ESTIVER JOGANDO
            if (estaJogando)
            {

                // OBTEM A TECLA PRESSIONADA
                int key = e.getKeyCode();

                // SE A TECLA FOR Z E O TIRO DO JOGADOR NÃO ESTIVER VISÍVEL
                // DISPARA OUTRO TIRO NA TELA
                if (key == KeyEvent.VK_Z)
                {
                    if (!tiro.isVisivel())
                    { tiro = new Tiro(x, y); }
                }
            }

        }
    }
}

WOOOOOOOOOOOOOOAH BIG! 605 linhas de puro código de funcionamento para um jogo tão simples como esse. UFA, mas agora vem a parte mais suave e final para o jogo funcionar.

CLASSE INVASORES DO ESPAÇO

A classe InvasoresDoEspaço é a mais básica somente para gerar o JFrame a abrir o JPanel na tela. Observem abaixo.

package INVASORESDOESPACO;

// Importação necessária para a classe
import javax.swing.JFrame;

/*
 *
 * AUTOR: CAIQUE MONTEIRO ARAUJO
 * DATA: 09/06/2013
 * CLASSE: INVASORESDOESPACO
 * OBJETIVO: TELA DO JOGO
 *
 */

public class InvasoresDoEspaco extends JFrame implements Comuns
{

    // MÉTODO CONTRUTOR DA CLASSE
    public InvasoresDoEspaco ()
    {
        // CRIA UMA NOVA GRADE NA TELA
        add(new Grade());

        // DEFINE O TITULO
        setTitle("Invasores do Espaço");
        // INFORMA O MÉTODO DE SAÍDA
        setDefaultCloseOperation(EXIT_ON_CLOSE);

        // SETA O TAMANHO
        setSize(LARGURA, ALTURA);
        // SETA A LOCALIZAÇÃO
        setLocationRelativeTo(null);
        // SETA A VISIBILIDADE
        setVisible(true);
        // SETA SE É REDIMENSIONAVEL
        setResizable(false);
    }

    // MÉTODO PRINCIPAL
    public static void main(String[] args)
    {
        // INSTÂNCIA UM NOVO JOGO
        new InvasoresDoEspaco();
    }

}

FINALMENTE ESSE MINI JOGO TÁ COMPLETO! UHUUUUU, tá, básico mais enfim tenho orgulho desse código. Abaixo eu mostro pra vocês a tela do jogo. ( PS. No jogo Snake eu dei os sprites que fiz, nesse usem a criatividade e criem um para o alien, jogador, bomba, tiro e explosão, as dimensões dessas imagens, estão no código do jogo )

quinta-feira, 13 de junho de 2013

[Tutorial] [Java] Jogo Invasores do Espaço - Parte 1

Hello people! Agora vamos ver um jogo diferente de Tetris, e Snake, TCHAAARÃN! O jogo é Invasores do Espaço, relativamente simples, entretanto com recurso de vilões ( MUAHAHAHA ) e vilões inteligentes. Esse tutorial vai dar a base para entender o funcionamento do comportamento entre classes diferentes, e permitir o desenvolvimento completo do jogo Pacman em Java, e continuação do desenvolvimento do Jogo em Plataforma (C#). Bom, basicamente para esse projeto teremos as seguintes classes:

InvasoresDoEspaco (principal, JFrame) - Exibe o jogo na tela
Grade (JPanel) - Controla todos processos do jogo

Comuns - Contém todas variáveis globais do jogo
Alienígenas - Controla os vilões do jogo
Jogador - Controla a nave principal do jogo
Tiro - Controla os tiros da nave pelo espaço do jogo
Desenho - Manipula o desenho de cada objeto do jogo

Para esse tutorial desenvolveremos as classes, na respectiva ordem, Comuns, Desenho, Alienígenas, Jogador e Tiro. Para o próximo tutorial desenvolveremos a Grade do jogo, juntamente com a classe principal.

CLASSE COMUNS

A classe Comuns, contém todas variáveis fixas do jogo. Vamos analisar o código abaixo ( lembrem-se de se atentar a todos comentários que faço durante o código ).

package INVASORESDOESPACO;

/*
 *
 * AUTOR: CAIQUE MONTEIRO ARAUJO
 * DATA: 09/06/2013
 * CLASSE: COMUNS
 * OBJETIVO: DEFINE AS VARIÁVEIS GLOBAIS DO JOGO
 *
 */

public interface Comuns
{

    // TAMANHO DA TELA
    public static final int LARGURA = 358;
    public static final int ALTURA = 350;

    // TAMANHO DA BASE DO JOGO
    public static final int BASE = 290;

    // ALTURA DA BOMBA
    public static final int BOMBA_HEIGHT = 5;

    // TAMANHO DO ALIENIGINA
    public static final int ALIEN_HEIGHT = 12;
    public static final int ALIEN_WIDTH = 12;

    // DEFINIÇÕES DA BORDA
    public static final int BORDA_DIREITA = 30;
    public static final int BORDA_ESQUERDA = 5;

    // VELOCIDADE DE DESLOCAMENTO GRAVITACIONAL
    public static final int VAI_ABAIXO = 15;

    // QUANTIDADE DE ALIENS
    public static final int NUMERO_DE_ALIENS = 24;

    // CHANCES DISPONÍVEIS
    public static final int CHANCES = 5;

    // DEFINIÇÃO DO DELAY
    public static final int DELAY = 17;

    // TAMANHO DO JOGADOR
    public static final int JOGADOR_WIDTH = 15;
    public static final int JOGADOR_HEIGHT = 10;
    
}

CLASSE DESENHO

A classe Desenho é responsável por manipular a imagem (Sprite), controlar a visibilidade e o plano cartesiano em (x,y) do objeto. O código é bem simples, conta somente com variáveis e os métodos get/set necessários para obter/setar esses valores. Vamos analisar o código abaixo.

package INVASORESDOESPACO;

// Importação necessária para a classe
import java.awt.Image;

/*
 *
 * AUTOR: CAIQUE MONTEIRO ARAUJO
 * DATA: 09/06/2013
 * CLASSE: DESENHO
 * OBJETIVO: RESPONSÁVEL POR MONTAR DESENHOS DO JOGO
 *
 */

public class Desenho
{

    // DEFINIÇÃO DA VISÍBILIDADE DO OBJETO NA TELA
    private boolean visivel;
    // CRIAÇÃO DE UMA NOVA IMAGEM
    private Image imagem;

    // VALORES (x,y) DO PLANO CARTESIANO
    protected int x;
    protected int y;

    // DEFINIÇÃO DO STATUS DO OBJETO
    protected boolean morrendo;

    // DEFINIÇÃO DA DIREÇÃO DO OBJETO NA TELA
    protected int dx;

    // MÉTODO CONSTRUTOR DA CLASSE
    public Desenho ()
    {
        // DEFINE COMO VISÍVEL
        visivel = true;
    }

    // TORNA O DESENHO INVISÍVEL
    public void morrer ()
    { visivel = false; }

    // OBTEM SE O OBJETO ESTÁ VISÍVEL OU NÃO
    public boolean isVisivel ()
    { return visivel; }

    // SETA A VISIBILIDADE DO OBJETO
    public void setVisivel (boolean visivel)
    { this.visivel = visivel; }

    // OBTEM A IMAGEM DO OBJETO
    public Image getImagem ()
    { return imagem; }

    // SETA A IMAGEM DO OBJETO
    public void setImagem (Image imagem)
    { this.imagem = imagem; }

    // OBTEM OS VALORES DO PLANO (x,y)
    public int getX ()
    { return x; }
    public int getY ()
    { return y; }

    // SETA OS VALORES DO PLANO (x,y)
    public void setX (int x)
    { this.x = x; }
    public void setY (int y)
    { this.y = y; }

    // OBTEM SE O DESENHO ESTÁ OU NÃO MORRENDO
    public boolean isMorrendo ()
    { return morrendo; }

    // SETA SE O DESENHO ESTÁ OU NÃO MORRENDO
    public void setMorrendo (boolean morrendo)
    { this.morrendo = morrendo; }

}

Muito bem!! Essa classe Desenho será um auxiliar para todos gráficos do jogo, e como podemos ver, ela é relativamente simples.

CLASSE ALIENÍGENAS

A classe Alienígenas é responsável por controlar o alienígena (vilão do jogo), estendendo a classe Desenho. Também é uma classe definitivamente simples, abaixo o código comentado com maiores informações.

package INVASORESDOESPACO;

// Importação necessária para a classe
import javax.swing.ImageIcon;

/*
 *
 * AUTOR: CAIQUE MONTEIRO ARAUJO
 * DATA: 09/06/2013
 * CLASSE: ALIENIGINAS
 * OBJETIVO: CONTROLA OS VILÕES DO JOGO
 *
 */

// EXTENDE A CLASSE AOS ATRIBUTOS E MÉTODOS DA CLASSE DESENHO
public class Alieniginas extends Desenho
{

    // DEFINE UMA BOMBA DA SUB-CLASSE BOMBA
    private Bomba bomba;
    // CRIA A STRING COM A URL DA IMAGEM DO ALIEN
    private final String alvo = "alien.png";

    // MÉTODO CONSTRUTOR DA CLASSE
    public Alieniginas (int x, int y)
    {
        // DEFINE O PLANO (x,y)
        this.x = x;
        this.y = y;

        // DEFINE UMA NOVA BOMBA A PARTIR DO PLANO (x,y) DO ALIEN
        bomba = new Bomba(x, y);

        // CRIA UM NOVO ICONE DE IMAGEM
        ImageIcon alien = new ImageIcon(alvo);
        // SETA A IMAGEM NA EXTENSÃO DA CLASSE DESENHO
        setImagem(alien.getImage());
    }

    // PARA O ALIEN SE MOVIMENTAR NO EIXO (x,y)
    public void atuarX (int direcao)
    { this.x += direcao; }
    public void atuarY (int direcao)
    { this.y += direcao; }

    // OBTÉM A BOMBA DESSE ALIEN
    public Bomba getBomba ()
    { return bomba; }

    // CRIA UMA SUB-CLASSE DE BOMBA COM EXTENSÃO EM DESENHO
    public class Bomba extends Desenho
    {
        // DEFINE A URL DA IMAGEM DA BOMBA
        private final String bomba = "bomba.png";
        // DEFINE SE A BOMBA ESTÁ DESTRUÍDA OU NÃO
        private boolean destruido;

        // MÉTODO CONSTRUTOR DA CLASSE
        public Bomba (int x, int y)
        {
            // DEFINE O PLANO (x,y)
            this.x = x;
            this.y = y;

            // CRIA UM NOVO ICONE DE IMAGEM
            ImageIcon bomba_ = new ImageIcon(bomba);
            // SETA A IMAGEM NA EXTENSÃO DA CLASSE DESENHO
            setImagem(bomba_.getImage());
        }

        // VERIFICA SE ESTÁ DESTRUIDO OU NÃO
        public boolean isDestruido ()
        { return destruido; }

        // SETA SE ESTÁ DESTRUIDO OU NÃO
        public void setDestruido (boolean destruido)
        { this.destruido = destruido; }
    }

}

Como observado a classe cria uma imagem do alien no plano (x,y) e deixa setado uma bomba para ele, possui métodos para para mover o alien no plano, e para verificar a destruição ou não da bomba.

CLASSE JOGADOR

A classe Jogador é responsável por criar o jogador na tela, permitir sua manipulação, estendendo a classe Desenho e ainda implementando as variáveis globais da classe Comuns. É uma classe definitivamente simples, implementando somente a possibilidade de interação com o teclado, vamos analisar agora para maiores detalhes.

package INVASORESDOESPACO;

// Importações necessárias para a classe
import java.awt.event.KeyEvent;
import javax.swing.ImageIcon;

/*
 *
 * AUTOR: CAIQUE MONTEIRO ARAUJO
 * DATA: 09/06/2013
 * CLASSE: JOGADOR
 * OBJETIVO: CONSTRÓI O JOGADOR
 *
 */

// ESTENDE A CLASSE AOS ATRIBUTOS E MÉTODOS DA CLASSE DESENHO
// E POSSUI A IMPLEMENTAÇÃO DA CLASSE COMUNS
public class Jogador extends Desenho implements Comuns
{

    // DEFINE AS COORDENADAS (x,y) DE INICIO
    private final int INICIAL_X = 270;
    private final int INICIAL_Y = 280;

    // CRIA A STRING COM A URL DA IMAGEM DO JOGADOR
    private final String jogador = "jogador.png";

    // DEFINE A LARGURA
    private int width;

    public Jogador ()
    {
        // CRIA UM NOVO ICONE DE IMAGEM
        ImageIcon jogador_ = new ImageIcon(jogador);
        // OBTEM A LARGURA DESSE ICONE
        width = jogador_.getImage().getWidth(null);

        // SETA A IMAGEM NA EXTENSÃO DA CLASSE DESENHO
        setImagem(jogador_.getImage());

        // SETA O PLANO (x,y) NA EXTENSÃO DA CLASSE DESENHO
        setX(INICIAL_X);
        setY(INICIAL_Y);
    }

    // DESLOCA A NAVE DO JOGADOR NA TELA
    public void atuar ()
    {
        // INCREMENTA NO X A DIREÇÃO RECEBIDA
        x += dx;

        // SE O X FOR MENOR QUE DOIS MANTEM ELE COMO 2
        if (x <= 2)
        { x = 2; }

        // SE O X FOR MAIOR QUE O LIMITE DA TELA, MANTEM ELE NO LIMITE DA TELA
        if (x >= LARGURA - 2*width)
        { x = LARGURA - 2*width; }
    }

    // CAPTURA O EVENTO CLICADO NO TECLADO
    public void keyPressed (KeyEvent e)
    {
        // RECEBE O CÓDIGO DA TECLA DIGITADO
        int key = e.getKeyCode();

        // SE A TECLA FOR PARA ESQUERDA DECREMENTA A DIREÇÃO
        if (key == KeyEvent.VK_LEFT)
        { dx = -2; }

        // SE A TECLA FOR PRA DIREITA INCREMENTA A DIREÇÃO
        if (key == KeyEvent.VK_RIGHT)
        { dx = 2; }
    }

    // CAPTURA O FIM DO CLIQUE NO TECLADO
    // QUANDO O USUÁRIO PARA DE CLICAR
    public void keyReleased (KeyEvent e)
    {
        // RECEBE O CÓDIGO DA TECLA DIGITADO
        int key = e.getKeyCode();

        // SE A TECLA FOR PARA ESQUERDA NÃO DESLOCA
        if (key == KeyEvent.VK_LEFT)
        { dx = 0; }

        // SE A TECLA FOR PARA DIREITA NÃO DESLOCA
        if (key == KeyEvent.VK_RIGHT)
        { dx = 0; }
    }
}

Facinho demaissssssssssssss, criando a imagem do desenho, atuando sobre uma direção na tela e alterando tal direção com as teclas. Ahhhhhhhhhh quem dera se todos jogos fossem fáceis assim. Enfim, let´s go para próxima classe.

CLASSE TIRO

A classe Tiro é responsável por controlar o tiro dado pelo jogador, estendendo a classe Desenho também. Mais simples ainda que as outras classe, veja o código.


package INVASORESDOESPACO;

// Importação necessária para a classe
import javax.swing.ImageIcon;

/*
 *
 * AUTOR: CAIQUE MONTEIRO ARAUJO
 * DATA: 09/06/2013
 * CLASSE: TIRO
 * OBJETIVO: REPRESENTA O TIRO DA NAVE
 *
 */

// EXTENDE A CLASSE AOS ATRIBUTOS E MÉTODOS DA CLASSE DESENHO
public class Tiro extends Desenho
{

    // CRIA A STRING COM A URL DA IMAGEM DO TIRO
    private String tiro = "tiro.png";

    // DEFINE O TAMANHO, E O ESPAÇAMENTO
    private final int H_SPACE = 6;
    private final int V_SPACE = 1;

    // MÉTODO CONSTRUTOR VAZIO DA CLASSE, INSTÂNCIA UM TIRO SEM DEFINIR
    // SUA POSIÇÃO NO AMBIENTE
    public Tiro () {}

    // MÉTODO CONSTRUTOR QUE RECEBE A POSIÇÃO DO TIRO
    public Tiro (int x, int y)
    {
        // CRIA UM NOVO ICONE DE IMAGEM
        ImageIcon tiro_ = new ImageIcon(tiro);
        // SETA A IMAGEM NA EXTENSÃO DA CLASSE DESENHO
        setImagem(tiro_.getImage());

        // DEFINE O PLANO (x,y) COM BASE NO TAMANHO E ESPAÇAMENTO DO TIRO
        setX(x + H_SPACE);
        setY(y - V_SPACE);
    }

}

UHUUUUU, acabou! Relativamente simples, não!? Na próxima parte do tutorial, vamos desenvolver a classe grade para manipular todo o jogo com seus objetos! Até lá pessoal.


[Tutoriais] Game em C++ - Parte 1

Olá caros amigos da Rede Globo ops, do blog! Hoje vamos começar uma BIG série de tutorial sobre Game em C++. Nesse blog estamos abordando três polos de linguagens em aplicações são elas C++, C# e JAVA. Bom, a escolha do C++ é simples e objetiva, essa linguagem é rápida, é flexível e é suportada em praticamente todas as máquinas. É a linguagem mais utilizada para games pois suporta os pacotes DirectX e OpenSource facilmente, ao final desse tutorial estaremos com um simples jogo prontinho e em funcionamento ( assim espero hahahaha ).

Para começar nossos projetos em C++ utilizaremos o Visual Studio C++ 2008 Express Edition ( eu gosto dessa versão pois é leve, simples e gratuita, mas o software fica a escolha de você, afinal aprenderemos somente o código e seus resultados ). Vou começar beeeeeeeeeeem do básico para que qualquer um aprenda, entenda e saiba criar sua própria lógica após todos tutoriais.

Bom, vamos lá, inicialmente vamos entender o C++. Para isso crie um novo projeto do tipo "Console Application" e eu nomeei o projeto como "Parte 1". Vamos analisar o projeto.



Na figura acima podemos observar as pastas HEADER FILES (São os aquivos do cabeçalho do programa), RESOURCE FILES (São os arquivos de recursos como imagens, textos, etc) e SOURCE FILES (São os aquivos do código em si).

Então vamos começar com o arquivo Parte1.cpp que é nosso arquivo principal. E execute o código abaixo, cuja o objetivo é apresentar na tela uma mensagem e recuperar a tecla de quebra de linha ( siiiiim, eu fiz em formato de imagem só pra vocês copiarem escrevendo o código, é a melhor maneira de saber o que você está fazendo ).


Bom, agora que já percebemos um pouco da linguagem, vamos começar a produção do nosso primeiro jogo em C++ na próxima parte, o jogo será em 2D, utilizando um auxiliar chamado SMFL para Visual C++ 2008, que pode ser baixado no link: http://downloads.sourceforge.net/sfml/SFML-1.6-dev-windows-vc2008.zip

Até a próxima!

[Blog] Próximos Tutoriais - Junho

Para quem acompanha o blog, segue abaixo uma lista de todos os próximos tutoriais que serão iniciados (alguns finalizados) no mês de junho:

CATEGORIA JOGOS
> Games em C++ (INICIADO)
> Jogo Invasores do Espaço em JAVA (CONCLUÍDO)
> Jogo PACMAN em JAVA (?)
> Jogo de Plataforma em C# (Parte 4 e parte 5)

CATEGORIA APLICATIVOS
> Aplicativo Thread em JAVA
> Manipulação de Imagem em JAVA
> Autômatos (?)

CATEGORIA DESIGN
> Video-Tutorial - Desenhos em Vetor (?)
> Video-Tutorial - Modelagem em 3DS MAX (?)

Os tutorias com (?) ainda estão em analise se serão finalizados e postados no mês de Junho.