1. Requirements description
1. Functional Requirements
In the functional requirements analysis stage, our main task is to specify which services the system must provide, define which functions the software completes, and provide them to those people. Functional requirements are a basic requirement of software development and an indispensable part of demand analysis. Tank War is a classic game. This game has learned some of the experiences of predecessors. Overall, the game is divided into both sides of the enemy and us. The tanks that mainly participate in the battle are controlled by players. The enemy tanks can appear intelligently and randomly on the screen and move, launching a certain number of bullets; players can move tanks at will in the specified area. When a bullet hits the player, the player dies and the game ends; enemy tanks run intelligently. Since they need to have a certain degree of intelligence, they appear randomly on the screen, and freely rotate, such as: knowing the steering when they encounter a boundary; bullets run: The tanks are controlled by players and fire bullets according to different tank positions. If they hit the target, an explosion effect will be produced; it will also disappear on the screen.
2. System performance requirements
The game's performance configuration requirements based on computer systems are to ensure that the program can run quickly and stably and can respond in a timely manner when running. When the player's tank is destroyed in the game, promptly prompt information about the game's failure and respond in a timely manner to meet the game's rule requirements. In addition, it is also necessary to ensure that the size of the main window cannot be changed at will when playing the game, ensuring playability.
3. Functional solutions
The code utilization rate is very good in the game. After all, it is a real-time work. Every millisecond, there will be many bullets fired, and the coordinate movement of many tanks. I compared the number of bullets hitting the tank countless times, and the keyboard monitoring events, implementing the thread interface, and drawing redrawing and refreshing; the sense of logic needs to be strong, and the object-oriented display is fully displayed; even the relationship between them is unclear, and it is easy to have unexpected situations; in order to make the addition of beauty and add explosion in the game, it requires that when the enemy tank dies, a short and fast carousel of fixed places pictures on the outside panel to achieve an explosion effect;
In general, the basic functions to be completed in tank battles include: graphical interface, differences in enemy-to-me tank styles, tanks can fire bullets to attack the opponent, but cannot attack teammates, and tanks set certain health points;
2. Main functions analysis
In the process of tank war game development, the main functions are provided to users for use, so first you have to draw a tank.
1. Draw the player tank: You need to set a paint() on the JPanel panel and draw the approximate shape of the tank with a brush;
2. Players' tanks can move: If the tank moves, they need to change the coordinates of the tank and constantly repaint the panel. However, when the tanks move, the event monitoring mechanism (keyboard monitoring) interface can be implemented in the panel class. When the player presses the w/d/s/a key, it can move up, down, left and right;
3. And draw enemy tanks on my drawing paper paint(); since enemy tanks and player tanks are on the same interface, they need to be drawn on the same drawing board;
4. Players' tanks can fire bullets: If a player wants to fire bullets, they need to have an event source. When the user presses the J key, the event monitoring will immediately fire a bullet, but it needs to be displayed in front of the user's eyes to see the effect, so paint() draws the bullet on the panel; since the bullet is launched and moves constantly towards the launch, the coordinates of the bullet must be changed constantly, and the bullet speed must be appropriate, so it needs to be implemented with threads and the panel is constantly redrawn to see the effect;
5. Players can fire bullets in a row and fire up to five: If the player wants to control the number of bullets, he needs to find out whether the number of bullets currently surviving is less than 5 when the player presses the J key. When the conditions are met, one bullet will be created. When the player fires more than five bullets, the system's fire function will no longer be called; since launching bullets does not only fire one bullet, set up a set of bullets to generate one bullet at a time to know that the bullets die when they hit the boundary and die;
6. When the player's tank hits the enemy tank, it disappears and produces an explosion effect; first, it is necessary to determine whether the player's tank's bullet hits the enemy, so there is a function to constantly judge the enemy. When the bullet runs on the enemy tank, the tank's life needs to end, and a bomb is generated, and a bomb is drawn in paint();
7. The enemy's tank can move intelligently: If the tank can only move, it needs to randomly generate the direction of movement. Due to constant motion, the method is written into the thread's run function and the thread is controlled to sleep to achieve the movement speed problem;
8. Enemy tanks can fire bullets: While drawing the enemy, set a certain dormant in the thread to generate bullets of different directions and different numbers of tanks, and take out each bullet on the panel and draw it;
9. When the enemy bullet hits the player, the player disappears: keep taking out each bullet of the enemy and comparing it with the player's tank. When the bullet touches the player, the player's explosion disappears;
3. Summary design
• Role attribute settings
Tank: the location where the tank is generated, the color of different types of tanks, the life identifier of the tank, the speed of the tank movement, and tanks in different directions;
Player Tank: After inheriting the basic attributes of the tank, it is realized on the basis of the second basis, and the player tank moves freely up and down and left and right; and the player tank has the function of firing and firing bullets;
Enemy tank: After inheriting the basic tank attributes, it is necessary to realize the intelligent movement of the enemy tank, and at the same time, it must also launch bullet threads on tanks from different positions;
Bullets: Bullets must have coordinate position, speed, health, and bullets should be able to move, and bullets must also implement the death function method;
Bomb: the coordinates of the bomb, life, and the effect method function of the gradually disappearing life;
•Functional property settings
Drawing paper: paint() should draw the player tank, enemy tank, and display the explosion effect of the death tank;
Event monitoring: When the user presses wdsa, the corresponding player tank should change direction. When the user fires j, there is a bullet in the direction of the launch, and it should run until death, unless it hits the enemy;
Hit the tank: When the bullet hits an enemy tank, an explosion is generated and added to the explosion set, and the explosion information is drawn on the surface;
Enemies hit the player: Take out the so-called enemies in the game and each enemy's bullets match my tank to determine whether to hit it;
Players hit the enemy: take out each bullet of the player, match each enemy tank to determine whether to hit it; and put the judgments related to hitting the tank into the thread run() to make continuous concurrent judgments;
The specific functional analysis diagram is as follows:
• Tank character attribute analysis diagram
Functional drawing board analysis diagram
Tank Xmind overall analysis diagram
Tank character attribute Xmind diagram
Tank function attributes Xmind diagram
IV. System implementation
•Members.java
//Members.javapackage mytank9;import java.util.*;class Bomb{// Define bomb coordinates int x, y;// The life of the bomb is int life = 9; boolean isLive = true; public Bomb(int x, int y) { this.x = x; this.y = y; }// Decrease health public void lifeDown() { if(life > 0) { life--; } else{ this.isLive = false; } }}class Shot implements Runnable{ int x; int y; int direct; int speed = 1; boolean isLive = true; public Shot(int x, int y, int direct) { this.x = x; this.y = y; this.direct = direct; } public void run() { while(true) { try{ Thread.sleep(50); }catch(Exception e){ e.printStackTrace(); } switch(direct) { case 0: y-=speed; break; case 1: x+=speed; break; case 2: y+=speed; break; case 3: x-=speed; break; }// Determine whether the field hits the edge if(x<0||x>400||y<0||y>300) { this.isLive = false; break; } } }}class Tank{// Tank horizontal coordinate int x = 0;// G vertical coordinate int y = 0;// Tank direction// 0 indicates upper, 1 indicates right, 2 indicates lower, 3 indicates left int direct = 0;// Tank speed int speed = 1;// Tank color int Color; 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 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; }}// Enemy tank class EnemyTank extends Tank implements Runnable{ int times = 0;// Define a vector that can store enemy bullets Vector<Shot>ss = new Vector<Shot>();// Enemy adds bullets after the tank and the enemy's tank has just been created and the enemy's tank has died public EnemyTank(int x, int y) { super(x, y); } @Override public void run() { // TODO Auto-generated method stub while(true) { switch(this.direct) { case 0: // Indicates that the tank is moving up for(int i = 0; i < 30; i++) {// Enemy tank moves in my range if(y>0) { y-=speed; } try { Thread.sleep(50); } catch (InterruptedException e) { // TODO Auto-generated catch block e.printStackTrace(); } } break; case 1: for(int i = 0; i < 30; i++) { if(x<400) { x+=speed; } try { Thread.sleep(50); } catch (InterruptedException e) { // TODO Auto-generated catch block e.printStackTrace(); } } break; case 2: for(int i = 0; i < 30; i++) { if(y<300) { y+=speed; } try { Thread.sleep(50); } catch (InterruptedException e) { // TODO Auto-generated catch block e.printStackTrace(); } } break; case 3: for(int i = 0; i < 30; i++) { if(x > 0) { x-=speed; } try { Thread.sleep(50); } catch (InterruptedException e) { // TODO Auto-generated catch block e.printStackTrace(); } } break; } // Determine whether you need to add a new bullet to the tank this.times++; if(times%2==0) { if(isLive) { if(ss.size()<5) { Shot s = null; switch(direct) { case 0: // Create a bullet s = new Shot(x+10, y, 0); // Add the bullet to the vector ss.add(s); break; case 1: s = new Shot(x+30, y+10, 1); ss.add(s); break; case 2: s = new Shot(x+10, y+30, 2); ss.add(s); break; case 3: s = new Shot(x, y+10, 3); ss.add(s); break; } // Start the bullet thread Thread t = new Thread(s); t.start(); } } } // Let the tank randomly generate a new direction this.direct = (int)(Math.random()*4);// Check whether the enemy tank dies if(this.isLive == false) {// After letting the tank die, exit the process break; } } }}// My tank class Hero extends Tank{ Vector<Shot> s = new Vector<Shot>(); Shot s = null; public Hero(int x, int y) { super(x, y); }// Fire public void shotEnemy() { switch(this.direct) { case 0:// Create a bullet s = new Shot(x+10, y, 0);// Add the bullet to the vector ss.add(s); break; case 1: s = new Shot(x+30, y+10, 1); ss.add(s); break; case 2: s = new Shot(x+10, y+30, 2); ss.add(s); break; case 3: s = new Shot(x, y+10, 3); ss.add(s); break; } Thread t = new Thread(s); t.start(); }// Tank move up public void moveUP() { y-=speed; }// Tank moveRight() { x+=speed; } public void moveDown() { y+=speed; } public void moveLeft() { x-=speed; }} •MyTankGame4.java
//MyTankGame4.java/* * Function: Tank Game 2.0 * 1: Draw the tank * 2: My tank can move up and down * 3: Draw the enemy tank * 4: My tank can fire bullets * 5: Bullets can fire up (up to five consecutive shots) * 6: When my tank hits the enemy tank, the enemy disappears (explosion* 『 Determine whether the bullet hits the tank; when it will be called; 』 * Explosion: 1 Prepare three pictures first; 2 define Bomb class; 3 Put bombs when hitting the enemy tank Vector 4 Draw* 7: Enemy tanks move within my specified range* 8: Enemy tanks can also fire bullets* 9: When the enemy tank hits my tank, my tank disappear*/package mytank9;import java.awt.*;import javax.imageio.ImageIO;import javax.swing.*;import java.awt.event.*;import java.io.File;import java.util.*;public class MyTankGame4 extends JFrame{ MyPanel mp = null; public static void main(String[] args) { // TODO Auto-generated method stub MyTankGame4 mytankgame1 = new MyTankGame4(); } public MyTankGame4(){ mp = new MyPanel(); Thread t = new Thread(mp); t.start(); this.add(mp);// Register to listen this.addKeyListener(mp); this.setSize(400, 300); this.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE); this.setVisible(true); }}class MyPanel extends JPanel implements KeyListener,Runnable{// Define a My tank Hero hero = null;// Define the enemy's tank Vector<EnemyTank> ets = new Vector<EnemyTank>();// Define a set of bombs Vector<Bomb> bombs = new Vector<Bomb>();// How many enemy tanks are int enSize = 3;// // Define the switching of three images to form a bomb Image image1 = null; Image image2 = null; Image image3 = null;// Construct public MyPanel(){ hero = new Hero(100,100);// Initialization of enemy tank for(int i = 0; i <enSize; i++) {// Create the enemy tank object EnemyTank et = new EnemyTank((i+1)*50, 0); et.setColor(0); et.setDirect(2);// Start the enemy tank Thread t = new Thread(et); t.start();// Negotiate a bullet to the enemy tank Shot s = new Shot(et.x+10,et.y+30,2); et.ss.add(s); Thread t2 = new Thread(s); t2.start();// Join ets.add(et); } try{ image1 = ImageIO.read(new File("bomb_1.gif")); image2 = ImageIO.read(new File("bomb_2.gif")); image3 = ImageIO.read(new File("bomb_3.gif")); }catch(Exception e){ e.printStackTrace(); }// Initialize three images // image1 = Toolkit.getDefaultToolkit().getImage(Panel.class.getResource("/bomb_1.gif"));// image2 = Toolkit.getDefaultToolkit().getImage(Panel.class.getResource("/bomb_2.gif"));// image3 = Toolkit.getDefaultToolkit().getImage(Panel.class.getResource("/bomb_3.gif")); } //Repaint public void paint(Graphics g){ super.paint(g); g.fillRect(0, 0, 400, 300);// Draw your own tank if(hero.isLive==true) { this.drawTank(hero.getX(), hero.getY(), g, this.hero.direct, 1); } // Remove each bullet from ss and draw for(int i = 0; i <hero.ss.size(); i++) {// Take out the bullets Shot myShot = hero.ss.get(i);// Draw a bullet and draw one bullet. How to draw multiple bullets? traversal if(myShot!=null&&myShot.isLive==true) { g.draw3DRect(myShot.x, myShot.y, 1, 1, false); } if(myShot.isLive==false) {// Remove the bullet from the ss vector hero.ss.remove(myShot); } }// Draw the bomb for(int i = 0; i < bombs.size();i++) { Bomb b = bombs.get(i); if(b.life > 6) { g.drawImage(image1, bx, by,30,30, this); }else if(b.life>4) { g.drawImage(image2, bx, by,30,30, this); }else{ g.drawImage(image3, bx, by,30,30, this); }// reduce b's health value b.lifeDown();// If the bomb's health value ==0, kick it out if(b.life == 0) { bombs.remove(b); } }// Draw the enemy tank for(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);// Draw the enemy bullet for(int j = 0; j < et.ss.size();j++) { Shot enemyShot = et.ss.get(j); if(enemyShot.isLive) { g.draw3DRect(enemyShot.x, enemyShot.y, 1, 1, false); }else{// The enemy tank died et.ss.remove(enemyShot); } } } } } } } } }// Whether the enemy bullet hits me public void hitMe() {// Remove each enemy tank for(int i = 0; i < this.ets.size(); i++) {// Take out the enemy tank EnemyTank et = ets.get(i); if(et.isLive==true) { for(int j = 0; j < et.ss.size(); j++) { // Take out the bullet Shot enemyShot = et.ss.get(j); if(enemyShot.isLive==true) { this.hitTank(enemyShot, hero); } } } } } } } } }// Whether my bullet hits the enemy tank public void hitEnemyTank() {// Determine whether the enemy tank is hit for(int i = 0; i < hero.ss.size(); i++) { Shot myShot = hero.ss.get(i);// To determine whether the bullet is valid if(myShot.isLive==true) {// To take out each tank and judge for(int j = 0; j < ets.size(); j++) { EnemyTank et = ets.get(j); if(et.isLive==true) { this.hitTank(myShot,et); } } } } } } } } } } }// To write a function specifically to determine whether the bullet hits the tank public void hitTank(Shot s, Tank et) { switch(et.direct) { // If the enemy tank direction is the upper or lower case 0: case 2: 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;// Create a bomb and put it in Vector Bomb b = new Bomb(et.x, et.y); bombs.add(b); } case 1: case 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 Tank Death et.isLive = false; Bomb b = new Bomb(et.x, et.y); bombs.add(b); } } } } } } }// Draw the tank public void drawTank(int x , int y, Graphics g, int direct, int type) {// Tank type switch(type) { case 0: g.setColor(Color.cyan); break; case 1: g.setColor(Color.yellow); break; }// 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);// Draw the straight line g.drawLine(x+10, y+15, x+10, y); break; case 1:// To the right// 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 lower rectangle g.fill3DRect(x, y+15, 30, 5, false);// DrawLine(x+15, y+10, x+30, y+10); break; case 2:// Draw the tank below g.fill3DRect(x+15, y+10, x+30, y+10);// Draw the tank on the right g.fill3DRect(x+15, y+10, x+30, y+10);// Draw the tank on the right g.fill3DRect(x+15, y, 5, 30, false);// Draw the rectangle g.fill3DRect(x+5, y+5, 10, 20, false);// Draw the rectangle g.fill3DRect(x+5, y+5, 10, 20, false);// DrawLine(x+10, y+10, 10, 10);// Draw a straight line g.drawLine(x+10, y+15, x+10, y+30); break; 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);// DrawLine(x+15, y+10, x, y+10); break; } }//Press the key and process it. a left s down d to right w up. @Override public void keyTyped(KeyEvent e) { // TODO Auto-generated method stub } @Override public void keyPressed(KeyEvent e) { // TODO Auto-generated method 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 whether the player presses J// Fire if(this.hero.ss.size()<=4&&this.hero.isLive==true) { this.hero.shotEnemy(); } }// Panel must be repainted this.repaint(); } @Override public void keyReleased(KeyEvent e) { // TODO Auto-generated method stub } public void run(){ while(true) { try{ Thread.sleep(100); }catch(Exception e) { e.printStackTrace(); } this.hitEnemyTank();// Function determines whether the enemy's bullet hits me this.hitMe(); this.repaint(); } }}5. Test results
Yellow is the player, hit the player
Enemies fire bullets
The above is all the content of this article. I hope it will be helpful to everyone's learning and I hope everyone will support Wulin.com more.