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.

domingo, 9 de junho de 2013

[Tutorial] [Java] Jogo da Cobrinha (Snake)

Olá pessoal, ontem realizei um tutorial bem simples de Tetris em java, hoje vamos realizar um jogo talvez mais simples ainda, porém com mais recursos ( sejam espertos para analisar hehe ). Inicialmente crie um novo projeto de aplicação Java no NetBeans, ou em um programa de preferência. Como nome do projeto coloque SNAKE, e a classe principal com o nome Snake.

Inicialmente vamos manipular a classe Grade que contém o ambiente do jogo. O funcionamento é bastante simples, existe a cobrinha que pode ser movimenta para todas posições (cima, baixo, esquerda, direita) mas nunca para posições opostas (esquerda e direita, cima e baixo), a cobrinha come a comida, e aumenta o tamanho do corpo. Se a cobrinha colidir com ela mesma, ou sobre as bordas do jogo, então é fim de jogo. Para implementação disso existe a classe que denominei de Grade, vamos observar abaixo. ( To feliz aprendi a carregar o código-fonte corretamente no blog :') hahahaha )

package SNAKE;

// Importações necessárias para rodar o jogo
import java.awt.Color;
import java.awt.Font;
import java.awt.FontMetrics;
import java.awt.Graphics;
import java.awt.Image;
import java.awt.Toolkit;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import java.awt.event.KeyAdapter;
import java.awt.event.KeyEvent;

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

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

public class Grade extends JPanel implements ActionListener
{

    // Tamanho do JPanel em Largura x Altura
    private final int WIDTH_ = 400;
    private final int HEIGHT_ = 400;

    // Tamanho de cada ponto na tela
    private final int TAMANHO_PONTO = 10;
    // Tamanho total de pontos, multiplicando a largura e altura
    private final int TODOS_PONTOS = 1600;

    // Um valor aleatória para gerar posição
    private final int RAND_POSICAO = 29;
    // Um delay para o tempo de execução do jogo
    private final int DELAY = 140;

    // Definição do plano cartesiano (x,y) do jogo
    private int[] x = new int[TODOS_PONTOS];
    private int[] y = new int[TODOS_PONTOS];

    // Pontos da cobrinha
    private int pontos;
    // Posição (x,y) da comida
    private int comida_x;
    private int comida_y;

    // Contar pontuação
    private int PONTUAÇÃO = 0;
    // Mensagem da pontuação
    String SCORE = "PONTUAÇÃO: " + PONTUAÇÃO;
    // Fonte para escrever a pontuação, estilo da fonte
    Font SCORE_FONT = new Font("Consolas", Font.BOLD, 12);
    // Tamanho total da escrita na tela
    FontMetrics SCORE_METRICA = this.getFontMetrics(SCORE_FONT);

    // Definição dos movimentos
    private boolean left = false;
    private boolean right = false;
    private boolean up = false;
    private boolean down = false;

    // Denifição do status do jogo
    private boolean estaJogando = true;

    // Tempo de execução do jogo
    private Timer tempo;

    // Imagens da cabeça e corpo da cobrinha, e comida
    private Image bola;
    private Image comida;
    private Image cabeça;

    // Método construtor da classe
    public Grade ()
    {
        // Cria uma instrução de teclado
        addKeyListener(new TAdapter());

        // Seta o plano de fundo como preto
        setBackground(Color.BLACK);

        // Cria um icone do arquivo png e seta na imagem correspondente
        ImageIcon bola_ = new ImageIcon("bola.png");
        bola = bola_.getImage();

        // Cria um icone do arquivo png e seta na imagem correspondente
        ImageIcon comida_ = new ImageIcon("comida.png");
        comida = comida_.getImage();

        // Cria um icone do arquivo png e seta na imagem correspondente
        ImageIcon cabeça_ = new ImageIcon("cabeça.png");
        cabeça = cabeça_.getImage();

        // Define o foco para o JPanel
        setFocusable(true);
        // Define o tamanho da tela
        setSize(WIDTH_, HEIGHT_);

        // Inicializa do jogo
        initJogo();
    }

    // Método para inicializar o jogo
    public void initJogo()
    {
        // Define quantidade de pontos iniciais
        pontos = 3;

        // Define a posição em (x,y) de cada ponto
        for (int i = 0; i < pontos; i++)
        {
            x[i] = 50 - i*10;
            y[i] = 50;
        }

        // Gera a primeira comida
        localComida();

        // Inicia o tempo de execução do jogo
        tempo = new Timer(DELAY, this);
        tempo.start();
    }

    // Método para desenhar elementos na tela do jogo
    @Override
    public void paint (Graphics g)
    {
        // Define o atribuito para a classe própria
        super.paint(g);

        // Analisa se o jogo esta em andamento, se estiver desenha na tela,
        // se não estiver, o jogo é dado como o fim
        if (estaJogando)
        {
            // Desenha a comida no plano (x,y) do jogo
            g.drawImage(comida, comida_x, comida_y, this);

            // Para cada ponto da cobrinha, desenha a cabeça e o corpo
            // em (x,y)
            for (int i = 0; i < pontos; i++)
            {
                if (i == 0)
                { g.drawImage(cabeça, x[i], y[i], this); }
                else
                { g.drawImage(bola, x[i], y[i], this); }
            }

            // Desenha a pontuação na tela
            desenharPontuacao(g);

            // Executa a sincronia de dados
            Toolkit.getDefaultToolkit().sync();

            // Pausa os gráficos
            g.dispose();
        }
        else
        {
            // Executa o fim de jogo
            FimDeJogo(g);
        }
    }

    // Método para desenhar a pontuação na tela
    public void desenharPontuacao (Graphics g)
    {
        // Define a frase para escrever
        SCORE = "PONTUAÇÃO: " + PONTUAÇÃO;
        // Define o tamanho da fonte
        SCORE_METRICA = this.getFontMetrics(SCORE_FONT);

        // Define a cor da fonte
        g.setColor(Color.white);
        // Seta a fonte para o gráfico
        g.setFont(SCORE_FONT);
        // Desenha a fonte na tela
        g.drawString(SCORE, (WIDTH_ - SCORE_METRICA.stringWidth(SCORE)) - 10, HEIGHT_ - 10);
    }

    public void FimDeJogo (Graphics g)
    {
        // Define a frase para escrever
        String msg = "FIM DE JOGO! Sua pontuação: " + PONTUAÇÃO;
        // Define o estilo da fonte
        Font pequena = new Font("Consolas", Font.BOLD, 14);
        // Define o tamanho da fonte
        FontMetrics metrica = this.getFontMetrics(pequena);

        // Define a cor da fonte
        g.setColor(Color.white);
        // Seta a fonte para o gráfico
        g.setFont(pequena);
        // Desenha a fonte na tela
        g.drawString(msg, (WIDTH_ - metrica.stringWidth(msg)) / 2, HEIGHT_ / 2);
    }

    // Método para checar se a cobrinha comeu a comida
    public void checarComida ()
    {
        // Se ele comer na mesma posição (x,y) então aumenta o corpo da cobrinha
        // aumenta a pontuação e gera uma nova comida
        if ((x[0] == comida_x) && (y[0] == comida_y))
        {
            pontos++;
            PONTUAÇÃO++;
            localComida();
        }
    }

    // Método para mover a cobrinha na tela
    public void mover ()
    {
        // Para cada ponto da cobrinha desenha em (x,y)
        for (int i = pontos; i > 0; i--)
        {
            x[i] = x[(i - 1)];
            y[i] = y[(i - 1)];
        }

        // Se for para esquerda decrementa em x
        if (left)
        {
            x[0] -= TAMANHO_PONTO;
        }

        // Se for para direita incrementa em x
        if (right)
        {
            x[0] += TAMANHO_PONTO;
        }

        // Se for para cima decrementa em y
        if (up)
        {
            y[0] -= TAMANHO_PONTO;
        }

        // Se for para baixo incrementa em y
        if (down)
        {
            y[0] += TAMANHO_PONTO;
        }
        
    }

    // Método para checar colisão entre a cobrinha e as bordas do jogo
    public void checarColisão ()
    {
        // Para cada ponto, verifica se este está em posição com outro ponto
        // se estiver ele avista que o jogador parou de jogar devido a colisão
        for (int i = pontos; i > 0; i--)
        {
            if ((i > 4) && (x[0] == x[i]) && (y[0] == y[i]))
            { estaJogando = false; }
            
        }

        // Verifica se a cabeça da cobrinha encostou em algum ponto (x,y)
        // nas bordas (width,height) da tela
        if (y[0] > HEIGHT_)
        { estaJogando = false; }

        if (y[0] < 0)
        { estaJogando = false; }

        if (x[0] > WIDTH_)
        { estaJogando = false; }

        if (x[0] < 0)
        { estaJogando = false; }
    }

    // Método que gera uma comida na tela
    public void localComida ()
    {
        // Define um valor aleatório e atribui a uma posição x na tela para a
        // comida
        int random = (int) (Math.random() * RAND_POSICAO);
        comida_x = (random * TAMANHO_PONTO);

        // Define um valor aleatório e atribui a uma posição y na tela para a
        // comida
        random = (int) (Math.random() * RAND_POSICAO);
        comida_y = (random * TAMANHO_PONTO);
    }

    // Método de ações durante a execução do jogo
    public void actionPerformed (ActionEvent e)
    {
        // Se estiver jogando então já realiza a checagem da comida, depois
        // verifica se existe colisão, só então depois, realiza o movimento
        // da cobrinha no jogo, por fim, redesenha os resultados
        if (estaJogando)
        {
            checarComida();
            checarColisão();
            mover();
        }

        repaint();
    }

    // Classe para analisar o teclado
    private class TAdapter extends KeyAdapter
    {

        // Método para verificar o que foi teclado
        @Override
        public void keyPressed (KeyEvent e)
        {
            // Obtém o código da tecla
            int key =  e.getKeyCode();

            // Verifica os movimentos e manipula as variáveis, para movimentar
            // corretamente sobre a tela
            if ((key == KeyEvent.VK_LEFT) && (!right))
            {
                left = true;
                up = false;
                down = false;
            }

            if ((key == KeyEvent.VK_RIGHT) && (!left))
            {
                right = true;
                up = false;
                down = false;
            }

            if ((key == KeyEvent.VK_UP) && (!down))
            {
                up = true;
                left = false;
                right = false;
            }

            if ((key == KeyEvent.VK_DOWN) && (!up))
            {
                down = true;
                left = false;
                right = false;
            }
        }
    }
 
}

Prontinhoooooooooooooooooooooo, uma Grade que engloba todos funcionamentos, eu comentei durante o código completo para que vocês conseguissem acompanhar o raciocínio. No trecho do código:

        // Cria um icone do arquivo png e seta na imagem correspondente
        ImageIcon bola_ = new ImageIcon("bola.png");
        bola = bola_.getImage();

        // Cria um icone do arquivo png e seta na imagem correspondente
        ImageIcon comida_ = new ImageIcon("comida.png");
        comida = comida_.getImage();

        // Cria um icone do arquivo png e seta na imagem correspondente
        ImageIcon cabeça_ = new ImageIcon("cabeça.png");
        cabeça = cabeça_.getImage();
É preciso criar as imagens na pasta principal do projeto, ou mude a url para a pasta que desejar. As images abaixo, foram as que criei para o jogo. O tamanho delas são 10x10 pixels, a primeira é para o corpo, a segunda é da cabeça da cobrinha e a terceira é da comida.

A Grade está pronta, mas agora é preciso exibi-la na tela, para isso vamos manipular a classe principal Snake que criamos no inicio do projeto, acompanhem.

package SNAKE;

// Importações necessárias para rodar o jogo
import javax.swing.JFrame;

/*
 *
 * AUTOR: CAIQUE MONTEIRO ARAUJO
 * DATA: 09/06/2013
 * CLASSE: SNAKE
 * OBJETIVO: JFRAME PRINCIPAL DO JOGO
 *
 */

public class Snake extends JFrame
{

    // Método construtor da classe
    public Snake ()
    {
        // Adiciona o JPanel do jogo
        add(new Grade());

        // Define a saida da aplicação
        setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
        // Define o tamanho da janela
        setSize(420, 440);
        // A localização
        setLocationRelativeTo(null);
        // O titulo da janela
        setTitle("Jogo da Cobrinha");

        // Impede o redimensionamento da janela
        setResizable(false);
        // Mostra a janela
        setVisible(true);
    }

    public static void main(String[] args) 
    {
        // Cria o novo JFrame
        new Snake();
    }

}

Muito bem!!!!!! Acabou, uhuuuuuu, e se rodarmos o jogo obtemos a tela abaixo:



TCHAAAAAAAARÃNNNNNN, final de mais um tutorial, espero que tenham aproveitado o conteúdo e entendido o código, criem novas ideias, implementem novos recursos, esse jogo não é orientado a objeto, entretanto é possível criar coisas interessantes. Até a próxima pessoal!


sábado, 8 de junho de 2013

[Tutorial] [Java] Jogo Tetris Simples - Parte 2 e Final

Olá pessoal!! Essa é a segunda e ultima parte do tutorial de jogo Tetris. Na primeira parte fizemos a classe Desenho, nesta parte faremos a classe Quadro e a classe principal Tetris. A classe Quadro é a maior e responsável por todo ambiente de funcionamento do jogo. Ela controla o iniciar, o pausar, os comandos, e os desenhos gráficos do game. Utilizando o mesmo procedimento explicado na primeira parte, crie uma nova classe chamada Quadro no pacote TETRIS. E a seguir, o código explicado em todos detalhes.

// Importações necessárias para funcionar a classe
import java.awt.Color;
import java.awt.Dimension;
import java.awt.Graphics;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import java.awt.event.KeyAdapter;
import java.awt.event.KeyEvent;

import javax.swing.JLabel;
import javax.swing.JPanel;
import javax.swing.Timer;

// Importação dos tipos de desenhos para a peça da classe Desenho
import TETRIS.Desenho.TetrisShape;

/*
 *
 * AUTOR: CAIQUE MONTEIRO ARAUJO
 * DATA: 06/06/2013
 * CLASSE: QUADRO
 * OBJETIVO: PAINEL DO JOGO
 *
 */

public class Quadro extends JPanel implements ActionListener
{

    // Tamanho do Quadro a ser gerado
    // Em uma tela de 250 x 400, usa-se 5% dos valores
    final int QuadroWidth  = 12;
    final int QuadroHeight = 20;

    // Define o tempo de execução no jogo
    Timer tempo;

    // Define os estados do jogo
    // QUANDO TERMINA DE CAIR
    boolean isCaindoAcabou = false;
    // QUANDO ESTÁ JOGANDO
    boolean isIniciado     = false;
    // QUANDO ESTÁ PAUSADO
    boolean isPausado      = false;

    // Define quantas linhas foram removidas
    int LinhasRemovidas = 0;

    // Define o (x,y) para a peça atual
    int atualX = 0;
    int atualY = 0;

    // Define o status do jogo
    JLabel status;

    // Define o desenho da peça atual
    Desenho atualPeça;

    // Define os tipos de quadros a serem desenhados
    TetrisShape[] quadro;

    // Método construtor da classe, recebendo JFrame principal
    // como parâmetro
    public Quadro (Tetris pai)
    {

        // Define o focus para este JPanel
        setFocusable(true);
        // Instância um novo desenho para a peça atual
        atualPeça = new Desenho();

        // Cria um novo tempo com velocidade 400, para este JPanel
        tempo = new Timer(400, this);
        tempo.start();

        // Obtém o status do jogo com o JFrame de parâmetro
        status = pai.getStatus();

        // Define quantas peças existirão no ambiente
        quadro = new TetrisShape[QuadroWidth * QuadroHeight];

        // Cria um novo KeyListener
        addKeyListener(new TAdapter());

        // Limpa o JPanel
        limparQuadro();
    }

    // Define o padrão da queda da peça no jogo
    public void actionPerformed (ActionEvent e)
    {
        // Se ela acabou de cair então define que ela ainda não acabou de cair
        // e cria um novo desenho, se não, ele desce uma linha a peça
        if (isCaindoAcabou)
        {
            isCaindoAcabou = false;
            novaPeça();
        }
        else
        {
            descerUmaLinha();
        }
    }

    // Define o tamanho de cada quadrado em Largura x Altura
    int quadradoWidth() { return (int) getSize().getWidth() / QuadroWidth; }
    int quadradoHeight() { return (int) getSize().getHeight() / QuadroHeight; }
    // Define em que posição (x,y) a peça será desenhada
    TetrisShape desenharEm(int x, int y) { return quadro[(y * QuadroWidth) + x]; }

    // Começa os eventos do jogo
    public void start()
    {
        // Se o jogo está pausado, impede de iniciar
        if (isPausado)
        { return; }

        // Define que o jogo iniciou, que a peça não acabou de cair
        // e que não existe ainda nenhum linha removida
        isIniciado = true;
        isCaindoAcabou = false;
        LinhasRemovidas = 0;

        // Limpa o JPanel
        limparQuadro();
        // Cria uma nova peça
        novaPeça();

        // Começa o tempo de execução do jogo
        tempo.start();
    }

    // Pausa os eventos do jogo
    public void pause()
    {
        // Se o jogo está pausado impede de continuar
        if (!isIniciado)
        { return; }

        // Define o pausado como inverso dele
        isPausado = !isPausado;

        // Se continua pausado então para a execução do tempo, e informa
        // que o jogo está pausado, se não, continua a execução do tempo
        // e resgada o status do jogo
        if (isPausado)
        {
            tempo.stop();
            status.setText("O jogo foi pausado!");
        }
        else
        {
            tempo.start();
            status.setText("Pontuação " + String.valueOf(LinhasRemovidas));
        }

        // Redesenha a tela
        repaint();
    }

    // Desenha a tela
    @Override
    public void paint (Graphics g)
    {
        // Define o método como Graphics
        super.paint(g);

        // Obtém o tamanho do JPanel
        Dimension tamanho = getSize();

        // Define o topo do JPanel
        int quadroTopo = (int) tamanho.getHeight() - QuadroHeight * quadradoHeight();

        // Cria um quadrado Tetris no top do JPanel
        for (int h = 0; h < QuadroHeight; h++)
        {
            for (int w = 0; w < QuadroWidth; w++)
            {
                // Informa onde será desenhado em (w,h)
                TetrisShape desenho = desenharEm(w, QuadroHeight - h - 1);

                // Se existir algum desenho então desenha o quadrado Tetris
                // na tela
                if (desenho != TetrisShape.SemDesenho)
                {
                    desenharQuadrado(g, 0 + w * quadradoWidth(),
                               quadroTopo + h * quadradoHeight(), desenho);
                }
            }
        }

        // Se existir desenho na peça atual
        if (atualPeça.getDesenho() != TetrisShape.SemDesenho)
        {
            // Para cada quadro, define a posição em (x,y) e desenha na tela
            for (int i = 0; i < 4; i++)
            {
                int x = atualX + atualPeça.x(i);
                int y = atualY - atualPeça.y(i);

                desenharQuadrado(g, 0 + x * quadradoWidth(),
                           quadroTopo + (QuadroHeight - y - 1) * quadradoHeight(),
                           atualPeça.getDesenho());
            }
        }
    }

    // Pular tela inteira
    private void pularParaBaixo()
    {
        // Define um novo Y como o Y da peça atual
        int newY = atualY;

        // Enquanto o novo Y for maior que 0
        while (newY > 0)
        {
            // Se ele não conseguir mover a peça pra baixo, então para
            if (!tentarMover(atualPeça, atualX, newY - 1))
            { break; }

            // Decrementa o novo Y
            --newY;
        }

        // Corta a peça
        cortarPeça();
    }

    // Descer uma linha no JPanel
    private void descerUmaLinha()
    {
        // Senão conseguir mover, corta a peça
        if (!tentarMover(atualPeça, atualX, atualY - 1))
        { cortarPeça(); }
    }

    // Limpa o JPanel
    private void limparQuadro()
    {
        // Para cada pixel na tela, define sem desenho
        for (int i = 0; i < QuadroHeight * QuadroWidth; i++)
        {
            quadro[i] = TetrisShape.SemDesenho;
        }
    }

    // Corta a peça
    private void cortarPeça()
    {
        // Verifica a posição de cada quadro do quadrado Tetris
        for (int i = 0; i < 4; ++i)
        {
            int x = atualX + atualPeça.x(i);
            int y = atualY - atualPeça.y(i);

            quadro[(y * QuadroWidth) + x] = atualPeça.getDesenho();
        }

        // Remove a linha completa
        removerLinhaCheia();

        // Se uma peça terminou de cair, cria uma nova peça
        if (!isCaindoAcabou)
        { novaPeça(); }
    }

    // Cria uma nova peça
    private void novaPeça()
    {
        // Seleciona um desenho aleatório
        atualPeça.setDesenhoAleatório();

        // Define o (x,y) da peça
        atualX = QuadroWidth / 2 + 1;
        atualY = QuadroHeight - 1 + atualPeça.minY();

        // Se não conseguir mover a peça, remove o desenho, para o tempo
        // cancela a execução, informa que é fim de jogo
        if (!tentarMover(atualPeça, atualX, atualY))
        {
            atualPeça.setDesenho(TetrisShape.SemDesenho);

            tempo.stop();
            isIniciado = false;

            status.setText("FIM DE JOGO!");
        }

    }

    // Tenta mover a peça para baixo
    private boolean tentarMover(Desenho novaPeça, int newX, int newY)
    {

        // Com base nos valores (x,y) da peça, desenha a peça em (x,y)
        // do JPanel
        for (int i = 0; i < 4; ++i)
        {
            int x = newX + novaPeça.x(i);
            int y = newY - novaPeça.y(i);

            // Retorna que foi impossivel mover
            if (x < 0 || x >= QuadroWidth || y < 0 || y >= QuadroHeight)
            { return false; }
            if (desenharEm(x, y) != TetrisShape.SemDesenho)
            { return false; }
        }

        // Define a peça atual, e o (x,y) atual da peça
        atualPeça = novaPeça;
        atualX    = newX;
        atualY    = newY;

        // Redesenha a peça na tela
        repaint();

        // Retorna que foi possivel mover
        return true;
    }

    // Remove uma linha cheia da tela
    private void removerLinhaCheia()
    {
        // Define linhas completas como zero
        int LinhasCompletas = 0;

        // Percorre para descobrir se a linha está cheia
        for (int i = QuadroHeight - 1; i >= 0; --i)
        {
            boolean linhaEstaCheia = true;

            for (int j = 0; j < QuadroWidth; ++j)
            {
                if (desenharEm(j, i) == TetrisShape.SemDesenho)
                {
                    linhaEstaCheia = false;
                    break;
                }
            }

            if (linhaEstaCheia)
            {
                ++LinhasCompletas;

                for (int k = i; k < QuadroHeight - 1; ++k)
                {
                    for (int j = 0; j < QuadroWidth; ++j)
                    {
                         quadro[(k * QuadroWidth) + j] = desenharEm(j, k + 1);
                    }
                }
            }
        }

        // Verifica quantas linhas foram removidas
        if (LinhasCompletas > 0)
        {
            LinhasRemovidas += LinhasCompletas;

            status.setText("Pontuação " + String.valueOf(LinhasRemovidas));

            isCaindoAcabou = true;
            atualPeça.setDesenho(TetrisShape.SemDesenho);
         
            repaint();
        }
    }

    // Desenha uma peça na tela
    private void desenharQuadrado(Graphics g, int x, int y, TetrisShape desenho)
    {
        Color colors[] = {
            new Color(0, 0, 0), new Color(204, 102, 102),
            new Color(102, 204, 102), new Color(102, 102, 204),
            new Color(204, 204, 102), new Color(204, 102, 204),
            new Color(102, 204, 204), new Color(218, 170, 0)
        };


        Color color = colors[desenho.ordinal()];

        g.setColor(color);
        g.fillRect(x + 1, y + 1, quadradoWidth() - 2, quadradoHeight() - 2);

        g.setColor(color.brighter());
        g.drawLine(x, y + quadradoHeight() - 1, x, y);
        g.drawLine(x, y, x + quadradoWidth() - 1, y);

        g.setColor(color.darker());
        g.drawLine(x + 1, y + quadradoHeight() - 1,
                         x + quadradoWidth() - 1, y + quadradoHeight() - 1);
        g.drawLine(x + quadradoWidth() - 1, y + quadradoHeight() - 1,
                         x + quadradoWidth() - 1, y + 1);

    }

    // Controla os eventos do teclado
    public class TAdapter extends KeyAdapter
    {
        @Override
         public void keyPressed (KeyEvent e)
         {

             // Se o jogo parar, ou não existir mais desenhos, dá um retorno
             if (!isIniciado || atualPeça.getDesenho() == TetrisShape.SemDesenho)
             { return; }

             // Obtém o código do teclado
             int keycode = e.getKeyCode();

             // Se for P, pausa o jogo e retorna
             if (keycode == 'p' || keycode == 'P') {
                 pause();
                 return;
             }

             // Se estiver pausado, retorna
             if (isPausado)
             { return; }

             switch (keycode)
             {
                 case KeyEvent.VK_LEFT:
                     tentarMover(atualPeça, atualX - 1, atualY);
                     break;
                 case KeyEvent.VK_RIGHT:
                     tentarMover(atualPeça, atualX + 1, atualY);
                     break;
                 case KeyEvent.VK_DOWN:
                     descerUmaLinha();
                     break;
                 case KeyEvent.VK_C:
                     tentarMover(atualPeça.girarDireita(), atualX, atualY);
                     break;
                 case KeyEvent.VK_Z:
                     tentarMover(atualPeça.girarEsquerda(), atualX, atualY);
                     break;
                 case KeyEvent.VK_SPACE:
                     pularParaBaixo();
                     break;
             }

         }
     }
 
}

WOOOOOOOOOOOW! Este código é gigante hein, mas não se assuste, existem maiores hehe enfim, a classe tem métodos start e pause que controlam o Timer de processos do jogo, paint e repaint que redesenham a tela. E outras funções para tentar mover a peça pelo espaço do jogo, remover as peças que completam 1 linha cheia na tela. Agora com a classe Desenho e Quadro concluídas, nos resta mexer na primeira classe criada no projeto como principal a classe Tetris. Ela é relativamente simples, veremos abaixo.

// Importações necessárias para funcionar a classe
import java.awt.BorderLayout;
import java.awt.Color;
import javax.swing.BorderFactory;

import javax.swing.JFrame;
import javax.swing.JLabel;

/*
 *
 * AUTOR: CAIQUE MONTEIRO ARAUJO
 * DATA: 06/06/2013
 * CLASSE: TETRIS
 * OBJETIVO: JFRAME PRINCIPAL DO JOGO
 *
 */

public class Tetris extends JFrame
{

    // Cria novo JLabel para o status
    JLabel status;

    // Método construtor da classe
    public Tetris ()
    {
        // Cria um novo JLabel e posiciona ao sul do JFrame
        status = new JLabel("Pontuação 0");
        // Adiciona o JLabel status ao JFrame
        add(status, BorderLayout.SOUTH);

        // Cria uma instância da classe Quadro
        Quadro jogo = new Quadro(this);
        // Define uma borda
        jogo.setBorder(BorderFactory.createLineBorder(Color.BLACK));
        // Adiciona o JPanel Quadro ao JFrame
        add(jogo);
        // Inicia o jogo
        jogo.start();

        // Seta o tamanho desta janela
        setSize(250, 400);
        // Seta o titulo
        setTitle("TETRIS - TUTORIAL");
        // Define método de sair da tela
        setDefaultCloseOperation(EXIT_ON_CLOSE);
    }

    // Método para obter o status de pontuação
    public JLabel getStatus ()
    {
        return status;
    }

    // Método main
    public static void main(String[] args)
    {

        // Cria uma instância desse própria classe
        Tetris jogo = new Tetris();

        // Manipula exibição na tela
        jogo.setLocationRelativeTo(null);
        jogo.setVisible(true);

    }
}

Muito bem! Na classe acima, criamos o JFrame que abre a janela com o JPanel (Quadro) e com status de pontuação. Tudo funcionando otimamente bem ;) A aparência visual do jogo pode ser vista abaixo:


Espero que tenham aproveitado o funcionamento do jogo completamente! Até a próxima pessoal ;)