1. Descrição dos requisitos
1. Requisitos funcionais
No estágio de análise de requisitos funcionais, nossa principal tarefa é especificar quais serviços o sistema deve fornecer, definir quais funções o software conclui e forneça -os a essas pessoas. Os requisitos funcionais são um requisito básico de desenvolvimento de software e uma parte indispensável da análise da demanda. Tank War é um jogo clássico. Este jogo aprendeu algumas das experiências de antecessores. No geral, o jogo é dividido em ambos os lados do inimigo e de nós. Os tanques que participam principalmente da batalha são controlados pelos jogadores. Os tanques inimigos podem aparecer de forma inteligente e aleatória na tela e se mover, lançando um certo número de balas; Os jogadores podem mover tanques à vontade na área especificada. Quando uma bala atinge o jogador, o jogador morre e o jogo termina; Os tanques inimigos correm de forma inteligente. Como eles precisam ter um certo grau de inteligência, eles aparecem aleatoriamente na tela e giram livremente, como: conhecer a direção quando encontram um limite; Balas executadas: os tanques são controlados por jogadores e balas de fogo, de acordo com diferentes posições do tanque. Se eles atingirem o alvo, um efeito de explosão será produzido; Ele também desaparecerá na tela.
2. Requisitos de desempenho do sistema
Os requisitos de configuração de desempenho do jogo com base em sistemas de computador são para garantir que o programa possa funcionar de forma rápida e estável e poder responder em tempo hábil ao executar. Quando o tanque do jogador é destruído no jogo, prontamente solicita informações sobre o fracasso do jogo e responda em tempo hábil para atender aos requisitos da regra do jogo. Além disso, também é necessário garantir que o tamanho da janela principal não possa ser alterado à vontade ao jogar o jogo, garantindo a jogabilidade.
3. Soluções funcionais
A taxa de utilização de código é muito boa no jogo. Afinal, é um trabalho em tempo real. Todo milissegundo, haverá muitas balas e o movimento de coordenadas de muitos tanques. Comparei o número de balas que atingem o tanque inúmeras vezes e os eventos de monitoramento do teclado, implementando a interface do encadeamento e desenhando redesenhando e refrescante; O senso de lógica precisa ser forte e a tela orientada a objetos é totalmente exibida; Mesmo o relacionamento entre eles não é claro, e é fácil ter situações inesperadas; Para fazer a adição de beleza e adicionar explosão no jogo, é necessário que, quando o tanque inimigo morra, um carrossel curto e rápido de lugares fixos de lugares no painel externo obtenha um efeito de explosão;
Em geral, as funções básicas a serem concluídas em batalhas de tanques incluem: interface gráfica, diferenças nos estilos de tanques inimigos para mim, os tanques podem disparar balas para atacar o oponente, mas não podem atacar colegas de equipe e os tanques estabelecem certos pontos de saúde;
2. Análise de funções principais
No processo de desenvolvimento de jogos de guerra de tanques, as principais funções são fornecidas aos usuários para uso, então primeiro você deve desenhar um tanque.
1. Desenhe o tanque do jogador: você precisa definir uma tinta () no painel JPanel e desenhe a forma aproximada do tanque com uma escova;
2. Os tanques dos jogadores podem se mover: se o tanque se mover, eles precisam alterar as coordenadas do tanque e repintar constantemente o painel. No entanto, quando os tanques se movem, a interface do mecanismo de monitoramento de eventos (monitoramento do teclado) pode ser implementada na classe de painel. Quando o jogador pressiona a tecla W/D/S/A, ele pode subir para cima, para baixo, para a esquerda e para a direita;
3. E desenhe tanques inimigos na minha tinta de papel de desenho (); Como os tanques inimigos e os tanques de jogadores estão na mesma interface, eles precisam ser desenhados na mesma prancheta;
4. Os tanques dos jogadores podem disparar balas: se um jogador quiser disparar balas, precisa ter uma fonte de evento. Quando o usuário pressiona a tecla J, o monitoramento do evento dispara imediatamente uma bala, mas precisa ser exibido na frente dos olhos do usuário para ver o efeito, então o pintura () desenha a bala no painel; Como a bala é lançada e se move constantemente em direção ao lançamento, as coordenadas da bala devem ser alteradas constantemente, e a velocidade da bala deve ser apropriada, por isso precisa ser implementada com threads e o painel é constantemente redesenhado para ver o efeito;
5. Os jogadores podem disparar balas seguidas e disparar até cinco: se o jogador quiser controlar o número de balas, ele precisa descobrir se o número de balas atualmente sobrevivendo é menor que 5 quando o jogador pressiona a tecla J. Quando as condições forem atendidas, uma bala será criada. Quando o jogador dispara mais de cinco balas, a função de incêndio do sistema não será mais chamada; Como o lançamento de balas não apenas dispara uma bala, configura um conjunto de balas para gerar uma bala de cada vez para saber que as balas morrem quando atingem o limite e morrem;
6. Quando o tanque do jogador atinge o tanque inimigo, ele desaparece e produz um efeito de explosão; Primeiro, é necessário determinar se a bala do tanque do jogador atinge o inimigo, então há uma função de julgar constantemente o inimigo. Quando a bala corre no tanque inimigo, a vida do tanque precisa terminar, e uma bomba é gerada, e uma bomba é desenhada em tinta ();
7. O tanque do inimigo pode se mover de forma inteligente: se o tanque só puder se mover, precisará gerar aleatoriamente a direção do movimento. Devido ao movimento constante, o método é gravado na função de execução do encadeamento e o encadeamento é controlado para dormir para alcançar o problema da velocidade de movimento;
8. Os tanques inimigos podem disparar balas: enquanto desenham o inimigo, defina um certo adormecido no fio para gerar balas de diferentes direções e diferentes números de tanques, e retirar cada bala no painel e desenhá -lo;
9. Quando a bala inimiga atinge o jogador, o jogador desaparece: continue tirando cada bala do inimigo e comparando -o com o tanque do jogador. Quando a bala toca o jogador, a explosão do jogador desaparece;
3. Design de resumo
• Configurações de atributo de função
Tanque: o local onde o tanque é gerado, a cor de diferentes tipos de tanques, o identificador de vida do tanque, a velocidade do movimento do tanque e os tanques em direções diferentes;
Tanque de jogadores: depois de herdar os atributos básicos do tanque, ele é realizado com base na segunda base, e o tanque do jogador se move livremente para cima e para baixo, para a esquerda e para a direita; e o tanque de jogadores tem a função de disparar e disparar balas;
Tanque inimigo: Depois de herdar os atributos do tanque básico, é necessário realizar o movimento inteligente do tanque inimigo e, ao mesmo tempo, ele também deve lançar fios de bala em tanques de diferentes posições;
Balas: as balas devem ter posição de coordenada, velocidade, saúde e balas devem ser capazes de se mover, e as balas também devem implementar o método da função da morte;
Bomba: As coordenadas da bomba, a vida e a função do método de efeito da vida gradualmente desaparecendo;
• Configurações funcionais de propriedades
PAPEL DE DESENHO: Paint () deve desenhar o tanque de jogador, tanque inimigo e exibir o efeito de explosão do tanque da morte;
Monitoramento de eventos: quando o usuário pressiona o WDSA, o tanque de jogador correspondente deve mudar de direção. Quando o usuário dispara j, há uma bala na direção do lançamento e deve correr até a morte, a menos que atinja o inimigo;
Bata no tanque: quando a bala atingir um tanque inimigo, uma explosão é gerada e adicionada ao conjunto de explosões, e as informações de explosão são desenhadas na superfície;
Os inimigos atingiram o jogador: retire os chamados inimigos no jogo e as balas de cada inimigo combinam com o meu tanque para determinar se os atingem;
Os jogadores atingem o inimigo: retire cada bala do jogador, combine cada tanque inimigo para determinar se deve atingi -lo; e coloque os julgamentos relacionados ao golpe no tanque no thread run () para fazer julgamentos concorrentes contínuos;
O diagrama de análise funcional específico é o seguinte:
• Diagrama de análise de atributo de caracteres do tanque
Diagrama de Análise da placa de desenho funcional
Diagrama de análise geral do tanque xmind
Diagrama do atributo de caracteres do tanque
Função do tanque atribui diagrama XMind
4. Implementação do sistema
• membros.java
//Members.javapackage mytank9; importar java.util. boolean islive = true; BOMBRA PUBLICA (int x, int y) {this.x = x; this.y = y; } // Diminuir a saúde public void lifeDown () {if (Life> 0) {Life--; } else {this.islive = false; }}} classe tiro implementa Runnable {int x; int y; int direto; int speed = 1; boolean islive = true; tiro público (int x, int y, int direto) {this.x = x; this.y = y; this.direct = direto; } public void run () {while (true) {try {thread.sleep (50); } catch (Exceção e) {e.printStackTrace (); } switch (direto) {case 0: y- = speed; quebrar; Caso 1: x+= velocidade; quebrar; Caso 2: y+= velocidade; quebrar; Caso 3: x- = velocidade; quebrar; } // Determine se o campo atinge a borda se (x <0 || x> 400 || y <0 || y> 300) {this.islive = false; quebrar; }}}} tanque de classe {// coordenadas horizontais do tanque int x = 0; // g coordenada vertical int y = 0; // direção do tanque // 0 indica superior, 1 indica à direita, 2 indica menor, 3 indica esquerda int direto = 0; // velocidade do tanque int = 1; // cor da cor do tanque int; boolean islive = true; public int getColor () {return color; } public void setColor (int color) {color = color; } public int getSpeed () {Return Speed; } public void setSpeed (int speed) {this.speed = speed; } public int getDirect () {return diretor; } public void SetDirect (int direto) {this.direct = direto; } tanque público (int x, int y) {this.x = x; this.y = y; } public int getx () {return x; } public void setx (int x) {this.x = x; } public int gety () {return y; } public void Sety (int y) {this.y = y; }} // Classe de tanque inimigo O tanque inimigo estende o tanque implementa runnable {int times = 0; // Defina um vetor que pode armazenar balas inimigas vetor <pat> ss = novo vetor <shot> (); // inimigo adiciona balas após o tanque e o tanque do inimigo e o tanque e o tanque e o tanque e o tanque do inimigo morreu; } @Override public void run () {// TODO Method Auto-Gerated Method Stub while (true) {switch (this.direct) {case 0: // indica que o tanque está subindo para (int i = 0; i <30; i ++) {// tanque inimigo se move na minha série se (y> 0) {y- = speed; } tente {thread.sleep (50); } catch (interruptedException e) {// TODO BLOCO DE CATCH AUTOGERATIDO E.PRINTSTACKTRACE (); } } quebrar; Caso 1: for (int i = 0; i <30; i ++) {if (x <400) {x+= speed; } tente {thread.sleep (50); } catch (interruptedException e) {// TODO BLOCO DE CATCH AUTOGERATIDO E.PRINTSTACKTRACE (); } } quebrar; Caso 2: for (int i = 0; i <30; i ++) {if (y <300) {y+= speed; } tente {thread.sleep (50); } catch (interruptedException e) {// TODO BLOCO DE CATCH AUTOGERATIDO E.PRINTSTACKTRACE (); } } quebrar; Caso 3: for (int i = 0; i <30; i ++) {if (x> 0) {x- = speed; } tente {thread.sleep (50); } catch (interruptedException e) {// TODO BLOCO DE CATCH AUTOGERATIDO E.PRINTSTACKTRACE (); } } quebrar; } // Determine se você precisa adicionar uma nova bala ao tanque. if (vezes%2 == 0) {if (islive) {if (ss.size () <5) {tiro s = null; switch (direto) {case 0: // Crie uma bala s = novo tiro (x+10, y, 0); // Adicione a bala ao vetor ss.add (s); quebrar; Caso 1: s = novo tiro (x+30, y+10, 1); ss.add (s); quebrar; Caso 2: S = novo tiro (x+10, y+30, 2); ss.add (s); quebrar; caso 3: s = novo tiro (x, y+10, 3); ss.add (s); quebrar; } // Inicie o thread da bala T = novo (s) thread (s); t.start (); }}} // Deixe o tanque gerar aleatoriamente uma nova direção this.direct = (int) (Math.random ()*4); // Verifique se o tanque inimigo morre se (thisLiSlive == false) {// Depois de deixar o tanque morrer, saia do processo quebrando; }}}} // meu herói da classe de tanque estende o tanque {vetor <pot> s = new Vector <Phot> (); Tiro s = nulo; herói público (int x, int y) {super (x, y); } // Fire public void shotEnemy () {switch (this.direct) {case 0: // Crie uma bala s = novo tiro (x+10, y, 0); // Adicione a bala ao vetor ss.Add (s); quebrar; Caso 1: s = novo tiro (x+30, y+10, 1); ss.add (s); quebrar; Caso 2: S = novo tiro (x+10, y+30, 2); ss.add (s); quebrar; caso 3: s = novo tiro (x, y+10, 3); ss.add (s); quebrar; } Thread t = novo (s) thread (s); t.start (); } // tanque move-se public void moveUp () {y- = speed; } // tank moveright () {x+= speed; } public void mudouwn () {y+= speed; } public void MoveleLeft () {x- = Speed; }} • mytankgame4.java
//Mytankgame4.java/* * função: jogo de tanque 2.0 * 1: desenhe o tanque * 2: meu tanque pode se mover para cima e para baixo * 3: desenhe o tanque inimigo * 4: meu tanque pode disparar bolas * 5: as balas podem disparar (até cinco tiros consecutivos * 6: quando meu tanque inimigo; Explosão: 1 prepare três fotos; java.awt.event.*; importar java.io.file; importar java.util MyTankGame4 () {mp = new MyPanel (); t.start (); this.add (MP); // Registre -se para ouvir isso.addkeyListener (MP); this.SetSize (400, 300); this.setDefaultCloseoperation (jframe.exit_on_close); this.setVisible (true); }} classe mypanel estende o jpanel implementa KeyListener, runnable {// define um herói do meu tanque hero = null; // Defina o vetor de tanque do inimigo <unenanyTank> ets = novo vetor <enemytank> (); // define a um conjunto de Bombs Vector <bomba> BOMBS = BOMBS = NewnyTank> (); 3; // // Defina a troca de três imagens para formar uma imagem de bomba imagem1 = null; Imagem imagem2 = nulo; Imagem imagem3 = null; // Construa public mypanel () {herói = new herói (100.100); // inicialização do tanque inimigo para (int i = 0; i <rensee; i ++) {// Crie o tanque inimigo EnemyTank et = new EnemyTank (i+1)*50, 0); et.setColor (0); et.setDirect (2); // Iniciar o thread do tanque inimigo t = novo thread (et); t.start (); // negocia uma bala para o tanque inimigo tiro s = novo tiro (et.x+10, et.y+30,2); et.ss.add (s); Tópico T2 = novo (s) thread (s); t2.start (); // JONE ETS.ADD (ET); } tente {image1 = imageio.read (novo arquivo ("bomb_1.gif")); image2 = imageio.read (novo arquivo ("bomb_2.gif")); image3 = imageio.read (novo arquivo ("bomb_3.gif")); } catch (Exceção e) {e.printStackTrace (); } // inicialize três imagens // image1 = Toolkit.getDefaultToolkit (). GetImage (pain.class.getResource ("/bomb_1.gif"); // image2 = toolkit.getDefaultToolkit (). GetImage (painel). Toolkit.getDefaultToolkit (). GetImage (painel.class.getResource ("/bomb_3.gif")); } // Repintar public void Paint (gráficos g) {super.paint (g); G.FillRect (0, 0, 400, 300); // Desenhe seu próprio tanque if (Hero.islive == true) {this.DrawTank (Hero.getx (), Hero.gety (), g, this.hero.direct, 1); } // Remova cada bala de SS e desenhe para (int i = 0; i <herói.ss.size (); i ++) {// tire as balas atiradas myshot = hero.ss.get (i); // desenhe uma bala e desenhe uma bala. Como desenhar várias balas? traversal if (myshot! = null && myshot.islive == true) {g.draw3drect (myshot.x, myshot.y, 1, 1, false); } if (myshot.islive == false) {// remova a bala do hero.ss.ss.remove (myShot); }} // desenhe a bomba para (int i = 0; i <bombs.size (); i ++) {bomba b = bombbs.get (i); if (B.Life> 6) {G.Drawimage (Image1, BX, por, 30.30, isso); } else if (b.life> 4) {g.drawimage (imagem2, bx, por, 30,30, isto); } else {g.drawimage (imagem3, bx, por, 30,30, isto); } // Reduza o valor da saúde de B B.Lifedown (); // Se o valor da saúde da bomba == 0, chute -o se (B.Life == 0) {Bombs.Remove (B); }} // desenhe o tanque inimigo para (int i = 0; i <ets.size (); i ++) {inimyTank et = ets.get (i); if (et.islive) {this.drawtank (et.getx (), et.gety (), g, et.getDirect (), 0); // desenhe a bala inimiga para (int j = 0; j <et.ss.size (); j ++) {shot inimyshot = et.s.get (j); if (inimyshot.islive) {g.draw3drect (inimyshot.x, inimyshot.y, 1, 1, falso); } else {// O tanque inimigo morreu et.ss.remove (inimyshot); }}}}}}}}} // se a bala inimiga me atinge public void hitMe () {// remova cada tanque inimigo para (int i = 0; i <this.ets.size (); i ++) {// retire o tanque inimigo inimigo et = sts.get (i); if (et.islive == true) {for (int j = 0; j <et.ss.size (); j ++) {// retire o tiro de bala inimyshot = et.ss.get (j); if (inimyshot.islive == true) {this.hittank (inimyshot, herói); }}}}}}}}} // se minha bala atinge o tanque inimigo public void hiteNemyTank () {// Determine se o tanque inimigo é atingido para (int i = 0; i <go.sS.size (); i ++) {thot myShot = Hero.Ss.get (i); {// para retirar cada tanque e julgar (int j = 0; j <ets.size (); j ++) {inimyTank et = ets.get (j); if (et.islive == true) {this.hittank (myshot, et); }}}}}}}}}}} // para escrever uma função especificamente para determinar se a bala atinge o tanque público vazio hittank (tiro S, tank et) {switch (et.direct) {// se a direção do tanque inimigo for a parte superior ou inferior 0: 2: if (sx> et.x && s.x <et.x+20 && s.y> et.y && s.y <et.y+30) {// atinge a morte s.islive = false; // tank Death et.islive = false; // cria uma bomba e coloque -a na bomba vetorial b = nova bomba (et.x e et.y); bombas.add (b); } Caso 1: Caso 3: if (sx> et.x && s.x <et.x+30 && s.y> et.y && s.y <et.y+20) {{// atinge a morte s.islive = false; // tanque inimigo Death et.islive = false; Bomba B = nova bomba (et.x, et.y); bombas.add (b); }}}}}}} // desenhe o tanque public void drawTank (int x, int y, gráficos g, int direto, int tipo) {// switch do tipo de tanque (tipo) {case 0: g.setColor (color.cyan); quebrar; Caso 1: G.setColor (color.yellow); quebrar; }// Tank direction switch(direct) {// Up case 0:// Draw the tank on the left g.fill3DRect(x, y, 5, 30, false);// DrawLine(x+10, y+15, y+15, 5, 30, false);// Draw the middle rectangle g.fill3DRect(x+5, y+5, 10, 20, false);// Draw the original shape g.fillOval(x+5, y+10, 10, 10); // desenhe a linha reta G.Drawline (x+10, y+15, x+10, y); quebrar; Caso 1: // para a direita // desenhe o retângulo superior g.fill3drect (x, y, 30, 5, falso); // desenhe o retângulo inferior g.fill3drect (x, y+15, 30, 5, false); // desenhar o retângulo inferior g.fill3drect (x+15, 30, 5, 5, false); // quebrar; Caso 2: // Desenhe o tanque abaixo de G.Fill3Drect (x+15, y+10, x+30, y+10); // desenhe o tanque na direita G.Fill3DRect (x+15, y+10, x+30, y+10); // desenhe o tanque na direita G.Fill3Drect (x+15, y, 5, 30, 30); // False); //, stange 5); 10, 20, false); // desenhe o retângulo G.Fill3Drect (x+5, y+5, 10, 20, false); // linha de sorteio (x+10, y+10, 10, 10); // desenhe uma linha reta G.Drawline (x+10, y+15, x+10, y+30); quebrar; Caso 3: // para a esquerda // desenhe o retângulo superior g.fill3drect (x, y, 30, 5, false); // desenhe o retângulo inferior g.fill3drect (x, y+15, 30, 5, false); // desenhe o retângulo médio g.fill3drect (x+5, y+5, 20, 10, 10; Linha de tração (x+15, y+10, x, y+10); quebrar; }} // Pressione a tecla e processe -a. a esquerda está descendo para a direita. @Override public void keytyped (keyEvent e) {// TODO Método Gerado Auto-Gerado Stub} @Override public void KeyPressed (KeyEvent E) {// TODO Método GOERADO Auto Stub if (e.getKeyCode () == keyEvent.vk_w) {this.hero.setDirect (0); this.hero.moveup (); } else if (e.getKeyCode () == keyEvent.vk_d) {this.hero.setDirect (1); this.hero.Moveright (); } else if (e.getKeyCode () == keyEvent.vk_s) {this.hero.setDirect (2); this.Hero.MoveDown (); } else if (e.getKeyCode () == keyEvent.vk_a) {this.hero.setDirect (3); this.Hero.MoveLeft (); } if (e.getKeyCode () == keyevent.vk_j) {// determine se o jogador pressiona j // dispara if (this.hero.sssize () <= 4 && this.herro.islive == true) {this.hero.shotenemy (); }} // O painel deve ser repintado this.Repaint (); } @Override public void keyreLeardeed (keyEvent e) {// TODO Método Gerado automático Stub} public void run () {while (true) {try {thread.sleep (100); } catch (Exceção e) {e.printStackTrace (); } this.hiteNemytank (); // função determina se a bala do inimigo me atinge this.hitMe (); this.Repaint (); }}}5. Resultados dos testes
Amarelo é o jogador, bata no jogador
Inimigos balas de fogo
O exposto acima é todo o conteúdo deste artigo. Espero que seja útil para o aprendizado de todos e espero que todos apoiem mais o wulin.com.