Curso completo de linguagem C++
Gameprog - Escola de programação de jogos digitais
Contato: gameprog.br@gmail.com
track19.html

index << >>

19. STL 2/5 <vector>

19.1 Visão geral Comumente nos jogos ocorre o processo de criação e destruição de elementos como criação de monstros para atacar o jogador e remoção dos mesmos quando o jogador os eliminam; outro exemplo comum, ocorre quando o jogador pressiona um botão de tiro no joystick, aonde os tiros que são criados devem ser adicionados em uma lista para serem manipulados um a um e estes mesmos tiros são removidos da lista quando eles ultrapassam o limite visível da tela ou outra condição que justificam a remoção dos mesmos. Nestes casos citados acima é muito comum o uso de um vetor de ponteiros para estes objetos.
// vetores_02.cpp // Ilustra o uso de vetores - parte 2 #include <iostream> #include <vector> using namespace std; // ----------------------- classse sistema --------------------------------- // ------ demonstra o uso de funções estáticas numa classe ----------------- class Sistema { public: static void inicio() { system("color f0"); system ("title vetores_02.cpp"); cout << "\n"; } // fim do metodo: inicio() static void fim() { cout << endl; system("pause"); } // fim do metodo: fim() }; // fim da classe sistema // ----------------------- classe monstro --------------------------------- class Monstro { public: int m_estrago; int m_id; static int id_automatico; Monstro(int estrago = 10): m_estrago(estrago) { m_id = id_automatico; id_automatico++; } // fim do construtor void atacar() { cout << "\t O monstro #" << m_id << " te atacou e vc perdeu "; cout << m_estrago << " pontos de energia" << "\n"; } // fim do método atacar() }; // fim da classe monstro int Monstro::id_automatico = 1; vector<Monstro *> lista_monstro; vector<Monstro *>::iterator ncx_iter; // ------------------ funções para manipular monstros ------------------------- void mostra_monstro() { for (ncx_iter = lista_monstro.begin(); ncx_iter != lista_monstro.end(); ncx_iter++) (*ncx_iter)->atacar(); } // fim da funcao monstro void monstro_vencido( int nMonstro) { nMonstro = nMonstro - 1; ncx_iter = lista_monstro.begin() + nMonstro; lista_monstro.erase(ncx_iter); } // fim da função: monstro_vencido() // -------------------- início da função principal --------------------------- int main() { Sistema::inicio(); for (int ncx=0; ncx < 5; ncx++) { int temp_estrago = (ncx+1) * 11; lista_monstro.push_back( new Monstro( temp_estrago) ); } for (int ncx=0; ncx < 5; ncx++) lista_monstro[ncx]->atacar(); cout << "\n\n \tO jogador matou o monstro #2 e #3\n"; cout << "\t--------------------------------------\n"; monstro_vencido (2); monstro_vencido(2); mostra_monstro(); Sistema::fim(); } // endmain
Funções estáticas numa classe // ----------------------- classse sistema --------------------------------- // ------ demonstra o uso de funcões estáticas numa classe ----------------- class Sistema { public: static void inicio() { system("color f0"); system ("title vetores_02.cpp"); cout << "\n"; } // fim do metodo: inicio() static void fim() { cout << endl; system("pause"); } // fim do metodo: fim() }; // fim da classe sistema Aqui nós transformamos nossas funções básicas de inicialização e finalização do nosso programa em métodos estáticos da classe Sistema. Como estas funções são estáticas não é necessário instanciar objetos para utilizá-las, bastando então precedê-las como o nome da classe desta forma: Sistema::inicio(); Sistema::fim(); Implementação da classe monstro // ----------------------- classse monstro --------------------------------- class Monstro { public: int m_estrago; int m_id; static int id_automatico; Monstro(int estrago = 10): m_estrago(estrago) { m_id = id_automatico; id_automatico++; } // fim do construtor Nossa classe Monstro não tem novidades. Definimos a propriedade m_estrago que representa a capacidade de estrago que o monstro pode fazer no jogador, m_id que é a identidade do monstro, e id_automatica que é uma variável estática para assinalar automaticamente o m_id do monstro criado. vector<Monstro *> lista_monstro; Nesta linha declaramos um vetor de ponteiros do tipo monstro. vector<Monstro *>::iterator ncx_iter; Nesta linha declaramos o iterator ncx_iter para acessarmos os elementos do vetor. Note que o tipo do iterator deve acompanhar o tipo do objeto que vamos ter no vetor (Monstro *). As duas linhas de código acima foram declaradas fora da função main() situação que deixa acessível globalmente a lista de monstros e o iterator. Funções para manipular monstros void mostra_monstro() { for (ncx_iter = lista_monstro.begin(); ncx_iter != lista_monstro.end(); ncx_iter++) (*ncx_iter)->atacar(); } // fim da funcao monstro Uma vez que nós definimos nossa lista de monstros como global podemos acessá-la em qualquer função. Nesta função realizamos um ataque coletivo com todos os monstros existentes. Veja que como nosso vetor é de ponteiros você deve usar esta sintaxe no iterator para acessar propriedades e métodos: (*ncx_iter)->atacar(); Removendo itens do vetor void monstro_vencido( int nMonstro) { nMonstro = nMonstro - 1; ncx_iter = lista_monstro.begin() + nMonstro; lista_monstro.erase(ncx_iter); } // fim da funcao: monstro_vencido() Você remove um elemento do vetor utilizando o método .erase( nPos ) passando para ele como um argumento um iterator com a posição do item, é por isso que utilizamos o iterator definido globalmente ncx_iter. Na função main() utilizamos esta linha para apagar o segundo item do vetor: monstro_vencido(2), ocorre que o vetor começa na posição 0 e é por isso que reduzimos 1 de nMonstro nesta função. Outro ponto muito importante é que quando deletamos um item do vetor, o vetor tem o seu tamanho reduzido e os itens abaixo do item deletado são movidos para as posições acima, é por isso que repetimos a linha monstro_vencido(2) para remover o terceiro item considerando a quantidade inicial do vetor. Criando os monstros for (int ncx=0; ncx < 5; ncx++) { int temp_estrago = (ncx+1) * 11; lista_monstro.push_back( new Monstro( temp_estrago) ); } Com o bloco de código acima, adicionamos cinco monstros em nosso vetor com cada monstro tendo uma capacidade de estrago diferente dado por (ncx+1) * 11; for (int ncx=0; ncx < 5; ncx++) lista_monstro[ncx]->atacar(); Nesta linha os monstros atacam. Note a sintaxe de chamada ao método devido ao uso de ponteiros. E finalmente, o jogador elimina alguns monstros... monstro_vencido (2); // Remove o segundo item e puxa os outros elementos... monstro_vencido(2); // ...uma posição acima. mostra_monstro(); Com as linhas acima removemos o segundo e terceiro item do vetor e na sequência os mostramos os monstros vivos.
index << >>


Produzido por Gameprog: Jair Pereira - Fev/2006 - Junho/2013 © gameprog.br@gmail.com http://www.gameprog.com.br