1. Descripción de requisitos
1. Requisitos funcionales
En la etapa de análisis de requisitos funcionales, nuestra tarea principal es especificar qué servicios debe proporcionar el sistema, definir qué funciones completa el software y proporcionarlos a esas personas. Los requisitos funcionales son un requisito básico de desarrollo de software y una parte indispensable del análisis de la demanda. Tank War es un juego clásico. Este juego ha aprendido algunas de las experiencias de los predecesores. En general, el juego se divide en ambos lados del enemigo y de nosotros. Los tanques que participan principalmente en la batalla están controlados por los jugadores. Los tanques enemigos pueden aparecer de manera inteligente y aleatoria en la pantalla y moverse, lanzando un cierto número de balas; Los jugadores pueden mover tanques a voluntad en el área especificada. Cuando una bala golpea al jugador, el jugador muere y el juego termina; Los tanques enemigos corren de manera inteligente. Dado que necesitan tener un cierto grado de inteligencia, aparecen al azar en la pantalla y giran libremente, como: conocer la dirección cuando se encuentran con un límite; Las balas corren: los tanques están controlados por jugadores y balas de fuego de acuerdo con diferentes posiciones de tanque. Si alcanzan el objetivo, se producirá un efecto de explosión; También desaparecerá en la pantalla.
2. Requisitos de rendimiento del sistema
Los requisitos de configuración de rendimiento del juego basados en sistemas informáticos son para garantizar que el programa pueda ejecutarse de manera rápida y estable y pueda responder de manera oportuna cuando se ejecuta. Cuando el tanque del jugador se destruye en el juego, indique rápidamente información sobre el fracaso del juego y responda de manera oportuna para cumplir con los requisitos de la regla del juego. Además, también es necesario asegurarse de que el tamaño de la ventana principal no se pueda cambiar a voluntad al jugar el juego, asegurando la jugabilidad.
3. Soluciones funcionales
La tasa de utilización del código es muy buena en el juego. Después de todo, es un trabajo en tiempo real. Cada milisegundo, habrá muchas balas disparadas y el movimiento coordinado de muchos tanques. Comparo el número de balas que llegan al tanque innumerables veces, y los eventos de monitoreo del teclado, implementando la interfaz de subprocesos y dibujando redibujando y refrescante; La sensación de lógica debe ser fuerte, y la pantalla orientada a objetos se muestra completamente; Incluso la relación entre ellos no está clara, y es fácil tener situaciones inesperadas; Para hacer la adición de belleza y agregar explosión en el juego, requiere que cuando el tanque enemigo muera, un carrusel corto y rápido de imágenes fijas en el panel exterior para lograr un efecto de explosión;
En general, las funciones básicas que se completan en las batallas de tanques incluyen: interfaz gráfica, diferencias en los estilos de tanques enemigos a mí, los tanques pueden disparar balas para atacar al oponente, pero no pueden atacar a los compañeros de equipo, y los tanques establecen ciertos puntos de salud;
2. Análisis de funciones principales
En el proceso de desarrollo de juegos de guerra de tanques, las funciones principales se proporcionan a los usuarios para su uso, por lo que primero debes dibujar un tanque.
1. Dibuja el tanque de reproductor: necesitas configurar una pintura () en el panel jpanel y dibujar la forma aproximada del tanque con un cepillo;
2. Los tanques de los jugadores pueden moverse: si el tanque se mueve, deben cambiar las coordenadas del tanque y volver a pintar constantemente el panel. Sin embargo, cuando los tanques se mueven, la interfaz del mecanismo de monitoreo de eventos (monitoreo del teclado) se puede implementar en la clase del panel. Cuando el jugador presiona la tecla W/D/S/A, puede moverse hacia arriba, hacia abajo, hacia la izquierda y hacia la derecha;
3. Y dibuja tanques enemigos en mi pintura de papel de dibujo (); Dado que los tanques enemigos y los tanques de jugadores están en la misma interfaz, deben ser dibujados en el mismo tablero de dibujo;
4. Los tanques de jugadores pueden disparar balas: si un jugador quiere disparar balas, necesita tener una fuente de evento. Cuando el usuario presiona la tecla J, el monitoreo del evento disparará inmediatamente una bala, pero debe mostrarse frente a los ojos del usuario para ver el efecto, por lo que pintar () dibuja la bala en el panel; Dado que la bala se lanza y se mueve constantemente hacia el lanzamiento, las coordenadas de la bala deben cambiarse constantemente, y la velocidad de la bala debe ser apropiada, por lo que debe implementarse con subprocesos y el panel se vuelve constantemente redibujado para ver el efecto;
5. Los jugadores pueden disparar balas en una fila y disparar hasta cinco: si el jugador quiere controlar la cantidad de balas, necesita averiguar si el número de balas que actualmente sobreviven es inferior a 5 cuando el jugador presiona la tecla J. Cuando se cumplan las condiciones, se creará una bala. Cuando el jugador dispara más de cinco balas, la función de fuego del sistema ya no se llamará; Dado que el lanzamiento de balas no solo dispara una bala, configura un conjunto de balas para generar una bala a la vez para saber que las balas mueren cuando golpean el límite y mueren;
6. Cuando el tanque del jugador golpea el tanque enemigo, desaparece y produce un efecto de explosión; Primero, es necesario determinar si la bala del tanque del jugador golpea al enemigo, por lo que existe una función para juzgar constantemente al enemigo. Cuando la bala corre sobre el tanque enemigo, la vida del tanque necesita terminar y se genera una bomba, y se dibuja una bomba en pintura ();
7. El tanque del enemigo puede moverse de manera inteligente: si el tanque solo puede moverse, necesita generar aleatoriamente la dirección de movimiento. Debido al movimiento constante, el método se escribe en la función de ejecución del hilo y el hilo se controla para dormir para lograr el problema de la velocidad de movimiento;
8. Los tanques enemigos pueden disparar balas: mientras dibujan al enemigo, coloque un cierto latente en el hilo para generar balas de diferentes direcciones y diferentes números de tanques, y saque cada bala en el panel y dibuje;
9. Cuando la bala enemiga golpea al jugador, el jugador desaparece: sigue sacando cada bala del enemigo y comparándola con el tanque del jugador. Cuando la bala toca al jugador, la explosión del jugador desaparece;
3. Diseño de resumen
• Configuración de atributos de rol
Tanque: la ubicación donde se genera el tanque, el color de los diferentes tipos de tanques, el identificador de vida del tanque, la velocidad del movimiento del tanque y los tanques en diferentes direcciones;
Tanque de jugador: después de heredar los atributos básicos del tanque, se realiza sobre la base de la segunda base, y el tanque de jugadores se mueve libremente hacia arriba y hacia abajo, hacia la izquierda y hacia la derecha; y el tanque de jugadores tiene la función de disparar y disparar balas;
Tanque enemigo: después de heredar los atributos básicos del tanque, es necesario realizar el movimiento inteligente del tanque enemigo, y al mismo tiempo, también debe lanzar hilos de bala en tanques desde diferentes posiciones;
Balas: las balas deben tener posición de coordenada, velocidad, salud y balas deben poder moverse, y las balas también deben implementar el método de función de muerte;
Bomba: las coordenadas de la bomba, la vida y la función del método del efecto de la vida que desaparece gradualmente;
• Configuración de propiedades funcionales
Papel de dibujo: pintar () debe dibujar el tanque de jugadores, el tanque enemigo y mostrar el efecto de explosión del tanque de muerte;
Monitoreo de eventos: cuando el usuario presiona WDSA, el tanque de reproductor correspondiente debe cambiar de dirección. Cuando el usuario dispara J, hay una bala en la dirección del lanzamiento, y debe correr hasta la muerte, a menos que golpee al enemigo;
Golpea el tanque: cuando la bala golpea un tanque enemigo, se genera una explosión y se agrega al conjunto de explosión, y la información de explosión se dibuja en la superficie;
Los enemigos golpean al jugador: elimine a los llamados enemigos en el juego y las balas de cada enemigo coinciden con mi tanque para determinar si golpearlo;
Los jugadores golpean al enemigo: eliminen cada bala del jugador, coincida con cada tanque enemigo para determinar si golpearlo; y poner los juicios relacionados con golpear el tanque en la ejecución del hilo () para hacer juicios concurrentes continuos;
El diagrama de análisis funcional específico es el siguiente:
• Diagrama de análisis de atributos de carácter de tanque
Diagrama de análisis de tablero de dibujo funcional
Tank Xmind Diagrama de análisis general
Atributo de carácter del tanque Diagrama Xmind
Atributos de la función del tanque Diagrama Xmind
IV. Implementación del sistema
• miembros.java
//Members.javapackage myTank9; import java.util.*; Bomba de clase {// Definir coordenadas de bomba int x, y; // La vida de la bomba es int life = 9; booleano islive = verdadero; bomba pública (int x, int y) {this.x = x; this.y = y; } // Disminuir la salud public void Lifedown () {if (vida> 0) {vida--; } else {this.islive = false; }}} La clase SHOT implementa Runnable {int x; int y; int directo; int velocidad = 1; booleano islive = verdadero; Shot Public (int x, int y, int directo) {this.x = x; this.y = y; this.direct = directo; } public void run () {while (true) {try {thread.sleep (50); } catch (Exception e) {E.PrintStackTrace (); } switch (directo) {caso 0: y- = velocidad; romper; Caso 1: x+= velocidad; romper; Caso 2: y+= velocidad; romper; Caso 3: x- = velocidad; romper; } // Determinar si el campo golpea el borde if (x <0 || x> 400 || y <0 || y> 300) {this.islive = false; romper; }}}} Class Tank {// Tank Horizontal Coordinate int x = 0; // g Coordinada vertical int y = 0; // La dirección del tanque // 0 indica superior, 1 indica a la derecha, 2 indica más abajo, 3 indica intent directo = 0; // Tank int velocidad = 1; // Color del tanque int; booleano islive = verdadero; public int getColor () {return color; } public void setColor (int color) {color = color; } public int getSpeed () {Velocidad de retorno; } public void setspeed (int speed) {this.speed = speed; } public int getDirect () {return direct; } public void setDirect (int direct) {this.direct = direct; } Public Tank (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; }} // La clase de tanque enemigo EnemyTank extiende el tanque implementa runnable {int Times = 0; // Definir un vector que puede almacenar balas enemigas Vector <Sot> ss = new Vector <shot> (); // Enemy agrega balas después de que el tanque y el tanque del enemigo acaban de crear y el tanque del enemigo ha muerto enemy enemyto (int x, int y) {súper (x, y); } @Override public void run () {// TODO STUB de método generado automático mientras (true) {switch (this.Direct) {case 0: // indica que el tanque se está moviendo para (int i = 0; i <30; i ++) {// enemy tanque se mueve en mi rango si (y> 0) {y- = velocidad; } try {thread.sleep (50); } Catch (InterruptedException e) {// TODO Auto Generado Bloque E.PrintStackTrace (); } } romper; Caso 1: para (int i = 0; i <30; i ++) {if (x <400) {x+= velocidad; } try {thread.sleep (50); } Catch (InterruptedException e) {// TODO Auto Generado Bloque E.PrintStackTrace (); } } romper; Caso 2: para (int i = 0; i <30; i ++) {if (y <300) {y+= velocidad; } try {thread.sleep (50); } Catch (InterruptedException e) {// TODO Auto Generado Bloque E.PrintStackTrace (); } } romper; Caso 3: para (int i = 0; i <30; i ++) {if (x> 0) {x- = velocidad; } try {thread.sleep (50); } Catch (InterruptedException e) {// TODO Auto Generado Bloque E.PrintStackTrace (); } } romper; } // Determinar si necesita agregar una nueva bala al tanque this.time ++; if (tiempos%2 == 0) {if (isLive) {if (ss.size () <5) {shot s = null; switch (directo) {case 0: // crea una bala s = nueva toma (x+10, y, 0); // Agregue la bala al vector ss.add (s); romper; caso 1: s = nuevo disparo (x+30, y+10, 1); ss.add (s); romper; caso 2: s = nuevo disparo (x+10, y+30, 2); ss.add (s); romper; Caso 3: S = nuevo disparo (x, y+10, 3); ss.add (s); romper; } // Inicie el hilo de la bala thing t = nuevo hilo (s); t.Start (); }}} // deja que el tanque genere aleatoriamente una nueva dirección this.direct = (int) (math.random ()*4); // verifique si el tanque enemigo muere si (this.islive == false) {// Después de dejar que el tanque muera, salga de la ruptura del proceso; }}}} // Mi héroe de clase de tanque extiende el tanque {vector <ot> s = nuevo vector <ot> (); Disparo s = nulo; héroe público (int x, int y) {super (x, y); } // Fire public void shotenemy () {switch (this.direct) {case 0: // crea una bala s = nueva disparo (x+10, y, 0); // Agregue la bala al vector ss.add (s); romper; caso 1: s = nuevo disparo (x+30, y+10, 1); ss.add (s); romper; caso 2: s = nuevo disparo (x+10, y+30, 2); ss.add (s); romper; Caso 3: S = nuevo disparo (x, y+10, 3); ss.add (s); romper; } Hilo t = nuevo hilo (s); t.Start (); } // Tank Move Up Public void MoveUp () {y- = velocidad; } // Tank Moveright () {x+= velocidad; } public void Moventown () {y+= velocidad; } public void Moveleft () {x- = velocidad; }} • MyTankGame4.java
//MyTankGame4.java/* * Función: Juego de tanque 2.0 * 1: Dibuja el tanque * 2: Mi tanque puede moverse hacia arriba y hacia abajo * 3: Dibuja el tanque enemigo * 4: Mi tanque puede disparar balas * 5: Las balas pueden encender (hasta cinco disparos consecutivos) * 6: Cuando mi tanque golpea el tanque enemigo, el enemigo desaparece (explica (explica el bullet. Explosión: 1 Prepare tres imágenes primero; java.awt.event.*; import java.io.file; import java.util.*; clase pública myTankGame4 extiende jframe {mypanel mp = null void void main (string [] MyTankGame4 () {mp = new MyPanel (); t.Start (); this.Add (MP); // Regístrese para escuchar esto.addkeylistener (MP); this.setsize (400, 300); this.setDefaultCloseOperation (jframe.exit_on_close); this.setVisible (verdadero); }} La clase MyPanel extiende JPanel implementa KeyListener, runnable {// Definir un tanque hero hero = null; // Defina el vector del tanque del enemigo <emyTank> ets = new vector <emyTank> (); // define un conjunto de bombas vector <bombr> bombas = new vector <bomb> ();//cuándo tantos enemys Últimos = 3; 3; 3; 3; // Defina el cambio de tres imágenes para formar una imagen de bomba Image1 = NULL; Imagen imagen2 = nulo; Imagen image3 = null; // construye public myPanel () {hero = new Hero (100,100); // Inicialización del tanque enemigo para (int i = 0; i <Ensize; i ++) {// Crea el objeto de tanque enemigo EnemyTank et = New EnemyTank ((i+1)*50, 0); et.SetColor (0); et.setDirect (2); // Inicie el hilo del tanque enemigo t = nuevo hilo (ET); t.start (); // negociar una bala al tanque enemigo dispara S = nuevo disparo (et.x+10, et.y+30,2); et.ss.add (s); Hilo t2 = nuevo hilo (s); t2.start (); // unirse a Ets.add (et); } try {image1 = imageIO.read (nuevo archivo ("bombe_1.gif")); image2 = imageIO.Read (nuevo archivo ("Bomb_2.gif")); image3 = imageIO.Read (nuevo archivo ("Bomb_3.gif")); } catch (Exception e) {E.PrintStackTrace (); } // Inicializar tres imágenes // Image1 = Toolkit.getDefaultToolkit (). Toolkit.getDefaultToolkit (). GetImage (panel.class.getResource ("/bombe_3.gif")); } // repintio de pintura pública void (gráficos g) {super.paint (g); G.Fillrect (0, 0, 400, 300); // Dibuja tu propio tanque if (hero.islive == verdadero) {this.drawTank (hero.getx (), hero.gety (), g, this.hero.direct, 1); } // Eliminar cada bala de SS y dibujar para (int i = 0; i <hero.ss.size (); i ++) {// Saque las balas disparadas myshot = hero.ss.get (i); // dibujar una bala y dibujar una bala. ¿Cómo dibujar múltiples balas? traversal if (myshot! = null && myshot.islive == true) {g.draw3drect (myshot.x, myshot.y, 1, 1, falso); } if (myshot.islive == false) {// elimina la bala del vector ss hero.ss.remove (myshot); }} // dibuja la bomba para (int i = 0; i <bombs.size (); i ++) {bomba b = bombs.get (i); if (b.life> 6) {g.drawimage (image1, bx, por, 30,30, esto); } else if (b.life> 4) {g.drawimage (imagen2, bx, por, 30,30, esto); } else {G.DrawImage (Image3, Bx, por, 30,30, esto); } // Reducir el valor de salud de B b.lifedown (); // Si el valor de salud de la bomba == 0, expulsarlo si (b.life == 0) {bombs.remove (b); }} // Dibuja el tanque enemigo para (int i = 0; i <ets.size (); i ++) {enemyTank et = ets.get (i); if (et.islive) {this.drawtank (et.getx (), et.gety (), g, et.getDirect (), 0); // dibujar la bala enemiga para (int j = 0; j <et.ss.size (); j ++) {disparó enemyshot = et.ss.get (j); if (enemyshot.islive) {g.draw3drect (enemyshot.x, enemyshot.y, 1, 1, falso); } else {// El tanque enemigo murió et.ss.remove (enemyshot); }}}}}}}}} // Si la bala enemiga me golpea public void hitMe () {// elimina cada tanque enemigo para (int i = 0; i <this.ets.size (); i ++) {// Take of the Enemy Tank EnemyTank et = ets.get (i); if (et.islive == true) {for (int j = 0; j <et.ss.size (); j ++) {// Saque la bala enemyshot = et.ss.get (j); if (enemyshot.islive == true) {this.hittank (enemyshot, hero); }}}}}}} Ial Saque cada tanque y juegue por (int j = 0; j <ets.size (); j ++) {enemyTank et = ets.get (j); if (et.islive == true) {this.hittank (myshot, et); }}}}}}}}}}} // para escribir una función específicamente para determinar si la bala golpea el tanque public void hittank (shot s, tank et) {switch (et.direct) {// if (sx> et.x && s.x <et.x+20 && s.y> et.y && s.y <et.y+30) {// hit death s.islive = false; // Tank Death et.islive = false; // Cree una bomba y la ponga en una bomba vectorial b = nueva bomba (et.x, 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) {{// hit death s.islive = false; // enemy tanque de la muerte et.islive = false; Bomba b = nueva bomba (et.x, et.y); bombas.add (b); }}}}}}} // Dibuja el tanque public void DrawTank (int x, int y, gráficos g, int direct, int type) {// Switch de tipo de tanque (tipo) {Case 0: G.SetColor (color.cyan); romper; Caso 1: G.SetColor (Color.ELLAK); romper; }// 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); // Dibuja la línea recta G.Drawline (x+10, y+15, x+10, y); romper; Caso 1: // a la derecha // Dibuje el rectángulo superior G.Fill3drect (x, y, 30, 5, falso); // Dibuja el rectángulo inferior G.Fill3drect (x, y+15, 30, 5, falso); // Dibuja el rectángulo inferior G.Fill3Drect (x, y+15, 30, 5, falso); // dibujo (x+15, y+10, x+30,+10,+10); romper; Caso 2: // Dibuje el tanque debajo de G.Fill3Drect (x+15, y+10, x+30, y+10); // Dibuje el tanque en la derecha G.Fill3drect (x+15, y+10, x+30, y+10); // Dibuje el tanque en el G.Fill3Drect correcto (x+15, y, 5, 30, falso); // Dibuje el recto G. y+5, 10, 20, falso); // Dibuja el rectángulo G.Fill3drect (x+5, y+5, 10, 20, falso); // Drawline (x+10, y+10, 10, 10); // dibujar una línea recta G.Drawline (x+10, y+15, x+10, y+30); romper; case 3:// To the left// Draw the upper rectangle g.fill3DRect(x, y, 30, 5, false);// Draw the lower rectangle g.fill3DRect(x, y+15, 30, 5, false);// Draw the middle rectangle g.fill3DRect(x+5, y+5, 20, 10, false);// Draw the circle g.fillOval(x+10, y+5, 10, 10); // Línea de acento (x+15, y+10, x, y+10); romper; }} // Presione la tecla y procesala. A la izquierda S BAJA D A DERECHA W UP. @Override public void keyTyped (KeyEvent E) {// TODO Método Generado automático} @Override public void keyPressed (keyEvent e) {// tODO stub de método generado automático 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.MoVoDown (); } else if (e.getKeyCode () == keyEvent.vk_a) {this.hero.setDirect (3); this.hero.moveleft (); } if (e.getKeyCode () == keyEvent.vk_j) {// Determinar si el reproductor presiona j // dispara if (this.hero.ss.size () <= 4 && this.hero.islive == true) {this.hero.shotenemy (); }} // El panel debe ser repintado this.rePaint (); } @Override public void KeyReleaded (KeyEvent E) {// TODO Método Generado automático} public void run () {while (true) {try {thread.sleep (100); } catch (Exception e) {E.PrintStackTrace (); } this.hitenemyTank (); // La función determina si la bala del enemigo me golpea esto.hitme (); this.Repaint (); }}}5. Resultados de la prueba
El amarillo es el jugador, golpea al jugador
Enemigos disparar balas
Lo anterior es todo el contenido de este artículo. Espero que sea útil para el aprendizaje de todos y espero que todos apoyen más a Wulin.com.