当前位置:   article > 正文

Java 坦克大战项目学习阶段记录及总结_tankwar 的java项目怎么学

tankwar 的java项目怎么学

/*首先要声明的是,这个并不是坦克大战项目编写细节的过程分享,只是个人的阶段学习记录及总结,坦克大战的项目可以参考B站上韩顺平老师的视频教学*/

阶段一:

小总结:今天刚开始,跟着视频一起学习编写坦克大战的项目,首先,我觉得对于编写一个项目,最重要的就是要构思好一个框架,比如,你写一个项目,要设几个类,每个类分别有什么作用。但是也不要太过于想提前想好要写什么方法(函数),我们只需要先构思好大的类,具体的,等到我们自己去写的时候,是可以慢慢再实现的。最重要的,一定是首先要有一个明确的思路。比如这个坦克大战的编写,目前写了五个类:主程序类,游戏界面绘制类,坦克基类,我的坦克类,敌方坦克类。思路是:先进行游戏界面的绘制,再画出坦克的图形,此时是静态的。然后再到动态的坦克编写,今天最后完成的,就是敌方坦克的绘制,因为敌方坦克会有许多特有的方法,所以要单独成一个类。因此,我对面向对象设计,或者说是对程序设计的感受是,最重要的就是有一个明确的思路,有一个框架,里面的内容是可以慢慢去填充的。  

今天“手痒”测试了一下,给敌方一个坦克添加了键盘监听事件,让我觉得写成之后,甚至可以写一个双人1V1的坦克大战,但是我在移动的时候,我发现,一次只能移动一辆坦克,要想同时移动两辆坦克,目前肯定是不行的。下一个阶段是学习多线程,因此我想到了实现多线程,应该就是为了多个坦克可以同时移动。

以下是今天的代码记录截图:

五个类(根据英文应该能猜到各自对应什么) 

1.主程序类(TankGame01)

  1. package com.wak.TankGame01Version;
  2. import javax.swing.*;
  3. /*坦克大战游戏主程序*/
  4. public class TankGame01 extends JFrame {
  5. public static void main(String[] args) {
  6. //启动!
  7. new TankGame01();
  8. }
  9. //定义GamePanel,创建游戏环境
  10. GamePanel gamePanel = null;
  11. //加载游戏环境
  12. public TankGame01(){
  13. //1.0版本
  14. this.setTitle("坦克大战1.0");
  15. //加载游戏环境
  16. gamePanel = new GamePanel();
  17. //将游戏区域加载到界面里
  18. this.add(gamePanel);
  19. //将键盘监听器加载到界面里
  20. this.addKeyListener(gamePanel);
  21. //设置界面可视化
  22. this.setVisible(true);
  23. //设置界面的大小
  24. this.setSize(1000,800);
  25. //设置界面可关闭
  26. this.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
  27. }
  28. }

2.游戏界面绘制类(GamePanel)

  1. package com.wak.TankGame01Version;
  2. import javax.swing.*;
  3. import java.awt.*;
  4. import java.awt.event.KeyEvent;
  5. import java.awt.event.KeyListener;
  6. import java.util.Vector;
  7. /*坦克大战的绘图区域*/
  8. public class GamePanel extends JPanel implements KeyListener {
  9. //定义一个自己的坦克
  10. MyTank myTank = null;
  11. //创建敌方坦克
  12. Vector<OpTank> opTanks = new Vector<>();
  13. //设置敌方坦克数量
  14. int opTanksSize = 3;
  15. public GamePanel(){
  16. myTank = new MyTank(200,600); //初始化坦克的位置
  17. myTank.setSpeed(3); //设置坦克的速度
  18. for(int i=0;i<opTanksSize;i++){
  19. OpTank opTank = new OpTank((100 * i + 100),0);
  20. opTank.setDirect(2);
  21. opTanks.add(opTank);
  22. }
  23. }
  24. @Override
  25. public void paint(Graphics g) {
  26. super.paint(g);
  27. g.fillRect(0,0,1000,800); //默认背景是黑色
  28. //画出坦克-封装方法
  29. DrawTank(myTank.getX(),myTank.getY(),g,myTank.getDirect(),0);
  30. DrawTank(myTank.getX(),myTank.getY(),g,myTank.getDirect(),0);
  31. for(int i=0;i<opTanks.size();i++){
  32. //取出敌方坦克
  33. OpTank opTank = opTanks.get(i);
  34. DrawTank(opTank.getX(),opTank.getY(),g,opTank.getDirect(),1);
  35. }
  36. }
  37. //编写方法,画出坦克
  38. /**
  39. *
  40. * @param x 坦克的x坐标
  41. * @param y 坦克的y坐标
  42. * @param g 画笔
  43. * @param direct 坦克方向(上下左右)
  44. * @param type 坦克类型
  45. */
  46. public void DrawTank(int x,int y,Graphics g,int direct,int type){
  47. //坦克的类型
  48. switch (type){
  49. case 0: //自己的坦克
  50. g.setColor(Color.CYAN);
  51. break;
  52. case 1: //敌人的坦克
  53. g.setColor(Color.RED);
  54. break;
  55. }
  56. switch (direct){
  57. case 0: //表示向上
  58. g.fill3DRect(x,y,10,60,false); //坦克的左边轮子
  59. g.drawLine(x,y + 10,x + 10,y + 10); //坦克左轮的履带
  60. g.drawLine(x,y + 20,x + 10,y + 20);
  61. g.drawLine(x,y + 30,x + 10,y + 30);
  62. g.drawLine(x,y + 40,x + 10,y + 40);
  63. g.drawLine(x,y + 50,x + 10,y + 50);
  64. g.fill3DRect(x + 40,y,10,60,false); //坦克的右边轮子
  65. g.drawLine(x + 40,y + 10,x + 50,y + 10); //坦克右轮的履带
  66. g.drawLine(x + 40,y + 20,x + 50,y + 20);
  67. g.drawLine(x + 40,y + 30,x + 50,y + 30);
  68. g.drawLine(x + 40,y + 40,x + 50,y + 40);
  69. g.drawLine(x + 40,y + 50,x + 50,y + 50);
  70. g.fill3DRect(x + 10,y + 10,30,40,false); //坦克的身体
  71. g.fillOval(x + 10,y + 15,30,30); //坦克的炮盖
  72. g.drawLine(x + 25,y + 30,x + 25,y); //坦克的炮筒
  73. break;
  74. case 1: //表示向右
  75. g.fill3DRect(x,y,60,10,false); //坦克左边的轮子
  76. g.drawLine(x + 10,y,x + 10 ,y + 10); //坦克左轮的履带
  77. g.drawLine(x + 20,y,x + 20 ,y + 10);
  78. g.drawLine(x + 30,y,x + 30 ,y + 10);
  79. g.drawLine(x + 40,y,x + 40 ,y + 10);
  80. g.drawLine(x + 50,y,x + 50 ,y + 10);
  81. g.fill3DRect(x,y + 40,60,10,false); //坦克右边的轮子
  82. g.drawLine(x + 10,y + 40,x + 10,y + 50);
  83. g.drawLine(x + 20,y + 40,x + 20,y + 50);
  84. g.drawLine(x + 30,y + 40,x + 30,y + 50);
  85. g.drawLine(x + 40,y + 40,x + 40,y + 50);
  86. g.drawLine(x + 50,y + 40,x + 50,y + 50);
  87. g.fill3DRect( x + 10,y + 10,40,30,false); //坦克的身体
  88. g.fillOval(x + 15,y + 10,30,30); //坦克的炮盖
  89. g.drawLine(x + 30,y + 25,x +60,y + 25); //坦克的炮筒
  90. break;
  91. case 2: //表示向下
  92. g.fill3DRect(x,y,10,60,false); //坦克的左边轮子
  93. g.drawLine(x,y + 10,x + 10,y + 10); //坦克左轮的履带
  94. g.drawLine(x,y + 20,x + 10,y + 20);
  95. g.drawLine(x,y + 30,x + 10,y + 30);
  96. g.drawLine(x,y + 40,x + 10,y + 40);
  97. g.drawLine(x,y + 50,x + 10,y + 50);
  98. g.fill3DRect(x + 40,y,10,60,false); //坦克的右边轮子
  99. g.drawLine(x + 40,y + 10,x + 50,y + 10); //坦克右轮的履带
  100. g.drawLine(x + 40,y + 20,x + 50,y + 20);
  101. g.drawLine(x + 40,y + 30,x + 50,y + 30);
  102. g.drawLine(x + 40,y + 40,x + 50,y + 40);
  103. g.drawLine(x + 40,y + 50,x + 50,y + 50);
  104. g.fill3DRect(x + 10,y + 10,30,40,false); //坦克的身体
  105. g.fillOval(x + 10,y + 15,30,30); //坦克的炮盖
  106. g.drawLine(x + 25,y + 30,x + 25,y + 60); //坦克的炮筒
  107. break;
  108. case 3: //表示向左
  109. g.fill3DRect(x,y,60,10,false); //坦克左边的轮子
  110. g.drawLine(x + 10,y,x + 10 ,y + 10); //坦克左轮的履带
  111. g.drawLine(x + 20,y,x + 20 ,y + 10);
  112. g.drawLine(x + 30,y,x + 30 ,y + 10);
  113. g.drawLine(x + 40,y,x + 40 ,y + 10);
  114. g.drawLine(x + 50,y,x + 50 ,y + 10);
  115. g.fill3DRect(x,y + 40,60,10,false); //坦克右边的轮子
  116. g.drawLine(x + 10,y + 40,x + 10,y + 50);
  117. g.drawLine(x + 20,y + 40,x + 20,y + 50);
  118. g.drawLine(x + 30,y + 40,x + 30,y + 50);
  119. g.drawLine(x + 40,y + 40,x + 40,y + 50);
  120. g.drawLine(x + 50,y + 40,x + 50,y + 50);
  121. g.fill3DRect( x + 10,y + 10,40,30,false); //坦克的身体
  122. g.fillOval(x + 15,y + 10,30,30); //坦克的炮盖
  123. g.drawLine(x + 30,y + 25,x,y + 25); //坦克的炮筒
  124. break;
  125. default:
  126. System.out.println("暂时没有处理");
  127. }
  128. }
  129. @Override
  130. public void keyTyped(KeyEvent e) {
  131. }
  132. @Override
  133. public void keyPressed(KeyEvent e) {
  134. if(e.getKeyCode() == KeyEvent.VK_W){
  135. myTank.setDirect(0);
  136. myTank.MoveUp();
  137. }else if(e.getKeyCode() == KeyEvent.VK_D){
  138. myTank.setDirect(1);
  139. myTank.MoveRight();
  140. }else if(e.getKeyCode() == KeyEvent.VK_S){
  141. myTank.setDirect(2);
  142. myTank.MoveDown();
  143. }else if(e.getKeyCode() == KeyEvent.VK_A){
  144. myTank.setDirect(3);
  145. myTank.MoveLeft();
  146. }
  147. // else if(e.getKeyCode() == KeyEvent.VK_UP){
  148. // opTanks.get(0).setDirect(0);
  149. // opTanks.get(0).MoveUp();
  150. // }else if(e.getKeyCode() == KeyEvent.VK_RIGHT){
  151. // opTanks.get(0).setDirect(1);
  152. // opTanks.get(0).MoveRight();
  153. // }else if(e.getKeyCode() == KeyEvent.VK_DOWN){
  154. // opTanks.get(0).setDirect(2);
  155. // opTanks.get(0).MoveDown();
  156. // }else if(e.getKeyCode() == KeyEvent.VK_LEFT) {
  157. // opTanks.get(0).setDirect(3);
  158. // opTanks.get(0).MoveLeft();
  159. // }
  160. this.repaint();
  161. }
  162. @Override
  163. public void keyReleased(KeyEvent e) {
  164. }
  165. }

3.坦克基类(Tank)

  1. package com.wak.TankGame01Version;
  2. /*坦克的基类*/
  3. public class Tank {
  4. private int x; //坦克的横坐标
  5. private int y; //坦克的纵坐标
  6. private int direct = 0; //坦克的方向
  7. private int speed = 1; //坦克的速度
  8. public Tank(){
  9. this.x = 100; //默认坦克的初始x坐标为100
  10. this.y = 100; //默认坦克的初始y坐标为100
  11. }
  12. public Tank(int x,int y){ //自己设置坦克的初始x,y坐标
  13. this.x = x;
  14. this.y = y;
  15. }
  16. //设置坦克的x坐标
  17. public void setX(int x){
  18. this.x = x;
  19. }
  20. //设置坦克的y坐标
  21. public void setY(int y){
  22. this.y = y;
  23. }
  24. //获得坦克的x坐标
  25. public int getX(){
  26. return x;
  27. }
  28. //获得坦克的y坐标
  29. public int getY(){
  30. return y;
  31. }
  32. //设置坦克的方向
  33. public void setDirect(int direct){
  34. this.direct = direct;
  35. }
  36. //获得坦克的方向
  37. public int getDirect(){
  38. return direct;
  39. }
  40. //设置坦克的速度
  41. public void setSpeed(int speed){
  42. this.speed = speed;
  43. }
  44. //获得坦克的速度
  45. public int getSpeed(){
  46. return speed;
  47. }
  48. //坦克的上右下左移动
  49. public void MoveUp(){
  50. y -= speed;
  51. }
  52. public void MoveRight(){
  53. x += speed;
  54. }
  55. public void MoveDown(){
  56. y += speed;
  57. }
  58. public void MoveLeft(){
  59. x -= speed;
  60. }
  61. }

4.我的坦克类(MyTank)

  1. package com.wak.TankGame01Version;
  2. /*自己的坦克*/
  3. public class MyTank extends Tank{
  4. //创建一个坦克
  5. private MyTank myTank = null;
  6. //设置坦克的初始化坐标
  7. public MyTank(int x,int y){
  8. this.setX(x);
  9. this.setY(y);
  10. }
  11. }

5.敌方坦克类(OpTank)

  1. package com.wak.TankGame01Version;
  2. public class OpTank extends Tank{
  3. private OpTank opTank = null;
  4. public OpTank(int x,int y){
  5. this.setX(x);
  6. this.setY(y);
  7. }
  8. }

运行效果:(蓝色是我的坦克,红色是敌方坦克,蓝色坦克可以上下左右移动)

阶段二:

小总结:今天接续昨天的内容,完成了我的坦克的发射炮弹,敌方坦克发射子弹,敌方坦克消失,敌方坦克自由移动,以及控制坦克移动的范围。我发现到这里,才真正写到了坦克大战的比较核心的、难的部分,那就是多线程。先简要的说一下今天学习的编写思路吧:因为炮弹是我的和敌方坦克都有的,所以需要单独写一个类,所以今天加了一个Shot类,但是因为你要射击的时候,它也要在界面上移动,所以这时候就需要用到多线程,像敌方坦克发射炮弹,敌方坦克移动,都是要用到多线程,而其中的另一个关键就是,在哪里启动,而这其中有很多思路是很巧妙的,比如,对于控制坦克的移动范围,我以为要另外写一个方法去进行判断的时候,韩老师的思路就是直接在控制坦克上下左右移动的代码上进行一个if判断,这样直接且非常巧妙的解决了问题,再比如,绘制敌方坦克的时候,先判断一下敌方坦克是否存活,再进行绘制,这样又提高了代码的运行效率,等等等。我发现,对于写一个程序,甚至是一段代码,一定要先想一想,构思一下,确立好思路再动手,尽量发散一下思维。

以下是今天的代码记录截图:

六个类(根据英文应该能猜到各自对应什么) 

 1.主程序类(TankGame01)

  1. package com.wak.TankGame01Version;
  2. import javax.swing.*;
  3. /*坦克大战游戏主程序*/
  4. public class TankGame01 extends JFrame {
  5. public static void main(String[] args) {
  6. //启动!
  7. new TankGame01();
  8. }
  9. //定义GamePanel,创建游戏环境
  10. GamePanel gamePanel = null;
  11. //加载游戏环境
  12. public TankGame01(){
  13. //1.0版本
  14. this.setTitle("坦克大战1.0");
  15. //加载游戏环境
  16. gamePanel = new GamePanel();
  17. //将游戏区域加载到界面里
  18. this.add(gamePanel);
  19. //将游戏界面的炮弹线程加入到界面里
  20. Thread thread = new Thread(gamePanel);
  21. //启动子线程
  22. thread.start();
  23. //将键盘监听器加载到界面里
  24. this.addKeyListener(gamePanel);
  25. //设置界面可视化
  26. this.setVisible(true);
  27. //设置界面的大小
  28. this.setSize(1000,800);
  29. //设置界面可关闭
  30. this.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
  31. }
  32. }

2.游戏界面绘制类(GamePanel)

  1. package com.wak.TankGame01Version;
  2. import javax.swing.*;
  3. import java.awt.*;
  4. import java.awt.event.KeyEvent;
  5. import java.awt.event.KeyListener;
  6. import java.util.Vector;
  7. /*坦克大战的绘图区域*/
  8. //为了监听键盘事件,实现KeyListener
  9. //
  10. public class GamePanel extends JPanel implements KeyListener,Runnable{
  11. //定义一个自己的坦克
  12. MyTank myTank = null;
  13. //创建敌方坦克
  14. Vector<OpTank> opTanks = new Vector<>();
  15. //设置敌方坦克数量
  16. int opTanksSize = 3;
  17. public GamePanel(){
  18. myTank = new MyTank(200,600); //初始化坦克的位置
  19. myTank.setSpeed(3); //设置坦克的速度
  20. for(int i=0;i<opTanksSize;i++){
  21. OpTank opTank = new OpTank((100 * i + 100),0);
  22. //设置方向
  23. opTank.setDirect(2);
  24. //启动敌人坦克线程
  25. new Thread(opTank).start();
  26. //给该opTank加入一颗炮弹
  27. Shot shot = new Shot(opTank.getX() + 25,opTank.getY() + 60,2);
  28. //存放到Vector中
  29. opTank.shots.add(shot);
  30. //启动线程对象
  31. new Thread(shot).start();
  32. //加入
  33. opTanks.add(opTank);
  34. }
  35. }
  36. @Override
  37. public void paint(Graphics g) {
  38. super.paint(g);
  39. g.fillRect(0,0,1000,800); //默认背景是黑色
  40. //画出坦克-封装方法
  41. //画出我的坦克
  42. DrawTank(myTank.getX(),myTank.getY(),g,myTank.getDirect(),0);
  43. //画出敌人的坦克
  44. for(int i=0;i<opTanks.size();i++){
  45. //取出敌方坦克
  46. OpTank opTank = opTanks.get(i);
  47. //判断敌方坦克是否存活
  48. if(opTank.isLive) { //当敌人坦克是存活的时候,才去画
  49. DrawTank(opTank.getX(), opTank.getY(), g, opTank.getDirect(), 1);
  50. //画出敌人的坦克发出的炮弹
  51. for (int j = 0; j < opTank.shots.size(); j++) {
  52. //取出子弹
  53. Shot shot = opTank.shots.get(j);
  54. //绘制
  55. if (shot.isLive) {
  56. g.setColor(Color.WHITE);
  57. g.fill3DRect(shot.x, shot.y, 4, 4, false);
  58. } else {
  59. opTank.shots.remove(shot);
  60. }
  61. }
  62. }
  63. }
  64. //画出我的坦克发出的炮弹
  65. if(myTank.shot != null && myTank.shot.isLive == true){
  66. g.setColor(Color.CYAN);
  67. g.fill3DRect(myTank.shot.x,myTank.shot.y,4,4,false);
  68. }
  69. }
  70. //编写方法,画出坦克
  71. /**
  72. *
  73. * @param x 坦克的x坐标
  74. * @param y 坦克的y坐标
  75. * @param g 画笔
  76. * @param direct 坦克方向(上下左右)
  77. * @param type 坦克类型
  78. */
  79. public void DrawTank(int x,int y,Graphics g,int direct,int type){
  80. //坦克的类型
  81. switch (type){
  82. case 0: //自己的坦克
  83. g.setColor(Color.CYAN);
  84. break;
  85. case 1: //敌人的坦克
  86. g.setColor(Color.RED);
  87. break;
  88. }
  89. switch (direct){
  90. case 0: //表示向上
  91. g.fill3DRect(x,y,10,60,false); //坦克的左边轮子
  92. g.drawLine(x,y + 10,x + 10,y + 10); //坦克左轮的履带
  93. g.drawLine(x,y + 20,x + 10,y + 20);
  94. g.drawLine(x,y + 30,x + 10,y + 30);
  95. g.drawLine(x,y + 40,x + 10,y + 40);
  96. g.drawLine(x,y + 50,x + 10,y + 50);
  97. g.fill3DRect(x + 40,y,10,60,false); //坦克的右边轮子
  98. g.drawLine(x + 40,y + 10,x + 50,y + 10); //坦克右轮的履带
  99. g.drawLine(x + 40,y + 20,x + 50,y + 20);
  100. g.drawLine(x + 40,y + 30,x + 50,y + 30);
  101. g.drawLine(x + 40,y + 40,x + 50,y + 40);
  102. g.drawLine(x + 40,y + 50,x + 50,y + 50);
  103. g.fill3DRect(x + 10,y + 10,30,40,false); //坦克的身体
  104. g.fillOval(x + 10,y + 15,30,30); //坦克的炮盖
  105. g.drawLine(x + 25,y + 30,x + 25,y); //坦克的炮筒
  106. break;
  107. case 1: //表示向右
  108. g.fill3DRect(x,y,60,10,false); //坦克左边的轮子
  109. g.drawLine(x + 10,y,x + 10 ,y + 10); //坦克左轮的履带
  110. g.drawLine(x + 20,y,x + 20 ,y + 10);
  111. g.drawLine(x + 30,y,x + 30 ,y + 10);
  112. g.drawLine(x + 40,y,x + 40 ,y + 10);
  113. g.drawLine(x + 50,y,x + 50 ,y + 10);
  114. g.fill3DRect(x,y + 40,60,10,false); //坦克右边的轮子
  115. g.drawLine(x + 10,y + 40,x + 10,y + 50);
  116. g.drawLine(x + 20,y + 40,x + 20,y + 50);
  117. g.drawLine(x + 30,y + 40,x + 30,y + 50);
  118. g.drawLine(x + 40,y + 40,x + 40,y + 50);
  119. g.drawLine(x + 50,y + 40,x + 50,y + 50);
  120. g.fill3DRect( x + 10,y + 10,40,30,false); //坦克的身体
  121. g.fillOval(x + 15,y + 10,30,30); //坦克的炮盖
  122. g.drawLine(x + 30,y + 25,x +60,y + 25); //坦克的炮筒
  123. break;
  124. case 2: //表示向下
  125. g.fill3DRect(x,y,10,60,false); //坦克的左边轮子
  126. g.drawLine(x,y + 10,x + 10,y + 10); //坦克左轮的履带
  127. g.drawLine(x,y + 20,x + 10,y + 20);
  128. g.drawLine(x,y + 30,x + 10,y + 30);
  129. g.drawLine(x,y + 40,x + 10,y + 40);
  130. g.drawLine(x,y + 50,x + 10,y + 50);
  131. g.fill3DRect(x + 40,y,10,60,false); //坦克的右边轮子
  132. g.drawLine(x + 40,y + 10,x + 50,y + 10); //坦克右轮的履带
  133. g.drawLine(x + 40,y + 20,x + 50,y + 20);
  134. g.drawLine(x + 40,y + 30,x + 50,y + 30);
  135. g.drawLine(x + 40,y + 40,x + 50,y + 40);
  136. g.drawLine(x + 40,y + 50,x + 50,y + 50);
  137. g.fill3DRect(x + 10,y + 10,30,40,false); //坦克的身体
  138. g.fillOval(x + 10,y + 15,30,30); //坦克的炮盖
  139. g.drawLine(x + 25,y + 30,x + 25,y + 60); //坦克的炮筒
  140. break;
  141. case 3: //表示向左
  142. g.fill3DRect(x,y,60,10,false); //坦克左边的轮子
  143. g.drawLine(x + 10,y,x + 10 ,y + 10); //坦克左轮的履带
  144. g.drawLine(x + 20,y,x + 20 ,y + 10);
  145. g.drawLine(x + 30,y,x + 30 ,y + 10);
  146. g.drawLine(x + 40,y,x + 40 ,y + 10);
  147. g.drawLine(x + 50,y,x + 50 ,y + 10);
  148. g.fill3DRect(x,y + 40,60,10,false); //坦克右边的轮子
  149. g.drawLine(x + 10,y + 40,x + 10,y + 50);
  150. g.drawLine(x + 20,y + 40,x + 20,y + 50);
  151. g.drawLine(x + 30,y + 40,x + 30,y + 50);
  152. g.drawLine(x + 40,y + 40,x + 40,y + 50);
  153. g.drawLine(x + 50,y + 40,x + 50,y + 50);
  154. g.fill3DRect( x + 10,y + 10,40,30,false); //坦克的身体
  155. g.fillOval(x + 15,y + 10,30,30); //坦克的炮盖
  156. g.drawLine(x + 30,y + 25,x,y + 25); //坦克的炮筒
  157. break;
  158. default:
  159. System.out.println("暂时没有处理");
  160. }
  161. }
  162. @Override
  163. public void keyTyped(KeyEvent e) {
  164. }
  165. @Override
  166. public void keyPressed(KeyEvent e) {
  167. if(e.getKeyCode() == KeyEvent.VK_W){
  168. myTank.setDirect(0);
  169. if(myTank.getY() > 0) {
  170. myTank.MoveUp();
  171. }
  172. }else if(e.getKeyCode() == KeyEvent.VK_D){
  173. myTank.setDirect(1);
  174. if(myTank.getX() + 60 < 1000) {
  175. myTank.MoveRight();
  176. }
  177. }else if(e.getKeyCode() == KeyEvent.VK_S){
  178. myTank.setDirect(2);
  179. if(myTank.getY() + 60 < 800) {
  180. myTank.MoveDown();
  181. }
  182. }else if(e.getKeyCode() == KeyEvent.VK_A){
  183. myTank.setDirect(3);
  184. if(myTank.getX() + 60 > 0) {
  185. myTank.MoveLeft();
  186. }
  187. }
  188. // else if(e.getKeyCode() == KeyEvent.VK_UP){
  189. // opTanks.get(0).setDirect(0);
  190. // opTanks.get(0).MoveUp();
  191. // }else if(e.getKeyCode() == KeyEvent.VK_RIGHT){
  192. // opTanks.get(0).setDirect(1);
  193. // opTanks.get(0).MoveRight();
  194. // }else if(e.getKeyCode() == KeyEvent.VK_DOWN){
  195. // opTanks.get(0).setDirect(2);
  196. // opTanks.get(0).MoveDown();
  197. // }else if(e.getKeyCode() == KeyEvent.VK_LEFT) {
  198. // opTanks.get(0).setDirect(3);
  199. // opTanks.get(0).MoveLeft();
  200. // }
  201. //如果玩家按下J键,我的坦克就会发出一个炮弹
  202. if(e.getKeyCode() == KeyEvent.VK_J){
  203. System.out.println("玩家按下了J键,开始射击!");
  204. myTank.shotOpTank();
  205. }
  206. this.repaint();
  207. }
  208. @Override
  209. public void keyReleased(KeyEvent e) {
  210. }
  211. @Override
  212. public void run() {
  213. while(true) {
  214. try {
  215. Thread.sleep(100);
  216. } catch (InterruptedException e) {
  217. e.printStackTrace();
  218. }
  219. //判断是否击中了敌人的坦克
  220. if(myTank.shot != null && myTank.shot.isLive){
  221. for(int i=0;i<opTanks.size();i++){ //遍历敌人的所有坦克
  222. HitTank(myTank.shot,opTanks.get(i));
  223. }
  224. }
  225. this.repaint();
  226. }
  227. }
  228. //编写方法判断炮弹是否打中坦克
  229. public void HitTank(Shot s,OpTank opTank){
  230. //判断是否击中坦克
  231. switch (opTank.getDirect()){
  232. case 0: //敌人坦克向上的方向
  233. case 2: //敌人坦克向下的方向
  234. if(s.x > opTank.getX() && s.x < opTank.getX() + 50 && s.y > opTank.getY() && s.y < opTank.getY() + 60){
  235. s.isLive = false;
  236. opTank.isLive = false;
  237. }
  238. break;
  239. case 1: //敌人坦克向右的方向
  240. case 3: //敌人坦克向左的方向
  241. if(s.x > opTank.getX() && s.x < opTank.getX() + 60 && s.y > opTank.getY() && s.y < opTank.getY() + 50){
  242. s.isLive = false;
  243. opTank.isLive = false;
  244. //当坦克被击中后将坦克从集合中移除
  245. opTanks.remove(opTank);
  246. }
  247. break;
  248. }
  249. }
  250. }

3.坦克基类(Tank)

  1. package com.wak.TankGame01Version;
  2. /*坦克的基类*/
  3. public class Tank {
  4. private int x; //坦克的横坐标
  5. private int y; //坦克的纵坐标
  6. private int direct = 0; //坦克的方向
  7. private int speed = 1; //坦克的速度
  8. public Tank(){
  9. this.x = 100; //默认坦克的初始x坐标为100
  10. this.y = 100; //默认坦克的初始y坐标为100
  11. }
  12. public Tank(int x,int y){ //自己设置坦克的初始x,y坐标
  13. this.x = x;
  14. this.y = y;
  15. }
  16. //设置坦克的x坐标
  17. public void setX(int x){
  18. this.x = x;
  19. }
  20. //设置坦克的y坐标
  21. public void setY(int y){
  22. this.y = y;
  23. }
  24. //获得坦克的x坐标
  25. public int getX(){
  26. return x;
  27. }
  28. //获得坦克的y坐标
  29. public int getY(){
  30. return y;
  31. }
  32. //设置坦克的方向
  33. public void setDirect(int direct){
  34. this.direct = direct;
  35. }
  36. //获得坦克的方向
  37. public int getDirect(){
  38. return direct;
  39. }
  40. //设置坦克的速度
  41. public void setSpeed(int speed){
  42. this.speed = speed;
  43. }
  44. //获得坦克的速度
  45. public int getSpeed(){
  46. return speed;
  47. }
  48. //坦克的上右下左移动
  49. public void MoveUp(){
  50. y -= speed;
  51. }
  52. public void MoveRight(){
  53. x += speed;
  54. }
  55. public void MoveDown(){
  56. y += speed;
  57. }
  58. public void MoveLeft(){
  59. x -= speed;
  60. }
  61. }

4.我的坦克类(MyTank)

  1. package com.wak.TankGame01Version;
  2. /*自己的坦克*/
  3. public class MyTank extends Tank{
  4. //创建一个坦克
  5. private MyTank myTank = null;
  6. Shot shot = null;
  7. //设置坦克的初始化坐标
  8. public MyTank(int x,int y){
  9. this.setX(x);
  10. this.setY(y);
  11. }
  12. //射击
  13. public void shotOpTank(){
  14. //设置炮弹的初始化坐标及方向
  15. switch (this.getDirect()){
  16. case 0:
  17. shot = new Shot(this.getX() + 25,this.getY(),0);
  18. break;
  19. case 1:
  20. shot = new Shot(this.getX() + 60,this.getY() + 25,1);
  21. break;
  22. case 2:
  23. shot = new Shot(this.getX() + 25,this.getY() + 60,2);
  24. break;
  25. case 3:
  26. shot = new Shot(this.getX(),this.getY() + 25,3);
  27. }
  28. //启动我们的Shot线程
  29. new Thread(shot).start();
  30. }
  31. }

5.敌方坦克类(OpTank)

  1. package com.wak.TankGame01Version;
  2. import java.util.Vector;
  3. public class OpTank extends Tank implements Runnable{
  4. private OpTank opTank = null; //创建一个敌方坦克
  5. boolean isLive = true; //敌方坦克的存活状态
  6. Vector<Shot> shots = new Vector<>(); //存储多个炮弹
  7. public OpTank(int x,int y){
  8. this.setX(x);
  9. this.setY(y);
  10. }
  11. @Override
  12. public void run() {
  13. while(true){
  14. switch (this.getDirect()){
  15. case 0:
  16. for(int i=0;i<80;i++) {
  17. if (getY() > 0){
  18. MoveUp();
  19. }
  20. //休眠
  21. try {
  22. Thread.sleep(50);
  23. } catch (InterruptedException e) {
  24. e.printStackTrace();
  25. }
  26. }
  27. break;
  28. case 1:
  29. for (int i=0;i<80;i++){
  30. if(getX() + 60< 1000) {
  31. MoveRight();
  32. }
  33. //休眠
  34. try {
  35. Thread.sleep(50);
  36. } catch (InterruptedException e) {
  37. e.printStackTrace();
  38. }
  39. }
  40. break;
  41. case 2:
  42. for (int i=0;i<80;i++){
  43. if(getY() + 60 < 1000) {
  44. MoveDown();
  45. }
  46. //休眠
  47. try {
  48. Thread.sleep(50);
  49. } catch (InterruptedException e) {
  50. e.printStackTrace();
  51. }
  52. }
  53. break;
  54. case 3:
  55. for (int i=0;i<80;i++){
  56. if(getY() + 60 < 800) {
  57. MoveLeft();
  58. }
  59. //休眠
  60. try {
  61. Thread.sleep(50);
  62. } catch (InterruptedException e) {
  63. e.printStackTrace();
  64. }
  65. }
  66. break;
  67. }
  68. setDirect((int)(Math.random() * 4));
  69. if(!isLive){
  70. break;
  71. }
  72. }
  73. }
  74. }

6.炮弹类(Shot)

  1. package com.wak.TankGame01Version;
  2. public class Shot implements Runnable{
  3. int x; //子弹的x坐标
  4. int y; //子弹的y坐标
  5. int direct = 0; //子弹的方向
  6. int speed = 2; //子弹的速度
  7. boolean isLive = true; //子弹的存活状态
  8. public Shot(int x,int y,int direct){
  9. this.x = x;
  10. this.y = y;
  11. this.direct = direct;
  12. }
  13. @Override
  14. public void run() { //射击
  15. while(isLive){
  16. //休眠
  17. try {
  18. Thread.sleep(50);
  19. } catch (InterruptedException e) {
  20. e.printStackTrace();
  21. }
  22. switch (direct){
  23. case 0: //向上
  24. y -= speed;
  25. break;
  26. case 1: //向右
  27. x += speed;
  28. break;
  29. case 2: //向下
  30. y += speed;
  31. break;
  32. case 3: //向左
  33. x -= speed;
  34. break;
  35. }
  36. System.out.println("炮弹的x坐标:" + x + ",炮弹的y坐标:" + y);
  37. //如果炮弹弹撞到墙壁,则销毁
  38. //当炮弹碰到敌人坦克时,也应当结束
  39. if(!(x >= 0 && x <= 1000 && y >=0 && y <= 800 && isLive)){
  40. isLive = false;
  41. System.out.println("炮弹已销毁");
  42. }
  43. }
  44. }
  45. }

运行效果截图:

阶段三:

小总结:今天完成了,坦克发射多颗炮弹,敌方坦克移动发射,我方坦克被炮弹击中,防止敌方坦克重叠,记录玩家成绩,记录敌人坦克信息。今天觉得比较有创新的点就是防止坦克重叠,还是以坦克的一个点出发,从坐标出发,这样思路就很明确。今天的一个小插曲是,最后韩老师还教了一个继续上局游戏的操作,但是,这个视频中,我发现,有很多内容之前都没学过,但是我先跟着敲了(这就为后面埋下了一个伏笔),结果当我正式运行的时候,开始新的游戏,是正常的,除了对记录击毁多少个敌人的次数,是上一局继承下来的(我觉得这个问题后面可以用一个if语句进行,清零操作),但是,当我继续上局游戏时,运行出来,敌方的坦克全部消失,然后我就又重新看视频,找问题,改了几个地方,发现越改越错,当时脑子直接懵了,然后我就一直Ctrl-Z,还好,最后改回来了,我本来想把这个内容加上去的,但是我发现以我现在的能力,我可以把这个时间去用来写一些跟游戏更贴切的内容,比如现在运行出来只有我的坦克和对面坦克,还没有掩体等,坦克的速度,初始位置,以及炮弹的速度,都还没有进行调试,相比于那个,这才是重点,这也是明天的内容。今天新增了一个Recorder类和一个Node类(记录坦克的位置信息等,但是由于后面的内容我没有继续再写了,这个类也就相当于白建的)。

以下是今天的代码记录截图:

七个类 (根据英文应该能猜到各自对应什么)

1.主程序类(TankGame01)

  1. package com.wak.TankGame01Version;
  2. import javax.swing.*;
  3. import java.awt.event.WindowAdapter;
  4. import java.awt.event.WindowEvent;
  5. /*坦克大战游戏主程序*/
  6. public class TankGame01 extends JFrame {
  7. public static void main(String[] args) {
  8. //启动!
  9. new TankGame01();
  10. }
  11. //定义GamePanel,创建游戏环境
  12. GamePanel gamePanel = null;
  13. //加载游戏环境
  14. public TankGame01(){
  15. //1.0版本
  16. this.setTitle("坦克大战1.0");
  17. //加载游戏环境
  18. gamePanel = new GamePanel();
  19. //将游戏区域加载到界面里
  20. this.add(gamePanel);
  21. //将游戏界面的炮弹线程加入到界面里
  22. Thread thread = new Thread(gamePanel);
  23. //启动子线程
  24. thread.start();
  25. //将键盘监听器加载到界面里
  26. this.addKeyListener(gamePanel);
  27. //设置界面可视化
  28. this.setVisible(true);
  29. //设置界面的大小
  30. this.setSize(1400,950);
  31. //设置界面可关闭
  32. this.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
  33. //在JFrame中增加相应关闭窗口的处理
  34. this.addWindowListener(new WindowAdapter() {
  35. @Override
  36. public void windowClosing(WindowEvent e) {
  37. Recorder.KeepRecord();
  38. System.exit(0);
  39. }
  40. });
  41. }
  42. }

2.游戏界面绘制类(GamePanel)

  1. package com.wak.TankGame01Version;
  2. import javax.swing.*;
  3. import java.awt.*;
  4. import java.awt.event.KeyEvent;
  5. import java.awt.event.KeyListener;
  6. import java.util.Vector;
  7. /*坦克大战的绘图区域*/
  8. //为了监听键盘事件,实现KeyListener
  9. //
  10. public class GamePanel extends JPanel implements KeyListener,Runnable{
  11. //定义一个自己的坦克
  12. MyTank myTank = null;
  13. //创建敌方坦克
  14. Vector<OpTank> opTanks = new Vector<>();
  15. //定义一个存放Node对象的Vector,用于恢复敌方坦克的坐标和方向
  16. Vector<Node> nodes = new Vector<>();
  17. //设置敌方坦克数量
  18. int opTanksSize = 6;
  19. public GamePanel(/*String key*/){
  20. // Recorder.getNodesAndEnemyTankRec();
  21. myTank = new MyTank(200,600); //初始化坦克的位置
  22. myTank.setSpeed(3); //设置坦克的速度
  23. //将GamePanel对象的 opTanks 设置给 Recorder 的 opTanks
  24. Recorder.setOpTanks(opTanks);
  25. for(int i=0;i<opTanksSize;i++){
  26. OpTank opTank = new OpTank((100 * i + 100),0);
  27. opTank.setOpTanks(opTanks);
  28. //设置方向
  29. opTank.setDirect(2);
  30. //启动敌人坦克线程
  31. new Thread(opTank).start();
  32. //给该opTank加入一颗炮弹
  33. Shot shot = new Shot(opTank.getX() + 25,opTank.getY() + 60,2);
  34. //存放到Vector中
  35. opTank.shots.add(shot);
  36. //启动线程对象
  37. new Thread(shot).start();
  38. //加入
  39. opTanks.add(opTank);
  40. }
  41. }
  42. //编写方法,显示我方击毁敌方坦克的信息
  43. public void showInfo(Graphics g){
  44. //画出玩家的总成绩
  45. g.setColor(Color.BLACK);
  46. Font font = new Font("宋体",Font.BOLD,25);
  47. g.setFont(font);
  48. g.drawString("您累计击毁敌方坦克的数量",1020,30);
  49. DrawTank(1020,60,g,0,1);
  50. g.setColor(Color.BLACK);
  51. g.drawString(Recorder.getAllOpTanksNum() + "",1080,100);
  52. }
  53. @Override
  54. public void paint(Graphics g) {
  55. super.paint(g);
  56. g.fillRect(0,0,1000,800); //默认背景是黑色
  57. showInfo(g);
  58. //画出坦克-封装方法
  59. //画出我的坦克
  60. if(myTank.isLive) {
  61. DrawTank(myTank.getX(), myTank.getY(), g, myTank.getDirect(), 0);
  62. }
  63. //画出敌人的坦克
  64. for(int i=0;i<opTanks.size();i++){
  65. //取出敌方坦克
  66. OpTank opTank = opTanks.get(i);
  67. //判断敌方坦克是否存活
  68. if(opTank.isLive) { //当敌人坦克是存活的时候,才去画
  69. DrawTank(opTank.getX(), opTank.getY(), g, opTank.getDirect(), 1);
  70. //画出敌人的坦克发出的炮弹
  71. for (int j = 0; j < opTank.shots.size(); j++) {
  72. //取出子弹
  73. Shot shot = opTank.shots.get(j);
  74. //绘制
  75. if (shot.isLive) {
  76. g.setColor(Color.WHITE);
  77. g.fill3DRect(shot.x, shot.y, 4, 4, false);
  78. } else {
  79. opTank.shots.remove(shot);
  80. }
  81. }
  82. }
  83. }
  84. //画出我的坦克发出的炮弹
  85. if(myTank.isLive) {
  86. for (int i = 0; i < myTank.shots.size(); i++) {
  87. if (myTank.shots.get(i) != null && myTank.shots.get(i).isLive == true) {
  88. g.setColor(Color.CYAN);
  89. g.fill3DRect(myTank.shots.get(i).x, myTank.shots.get(i).y, 4, 4, false);
  90. } else {
  91. myTank.shots.remove(i);
  92. }
  93. }
  94. }
  95. }
  96. //编写方法,画出坦克
  97. /**
  98. *
  99. * @param x 坦克的x坐标
  100. * @param y 坦克的y坐标
  101. * @param g 画笔
  102. * @param direct 坦克方向(上下左右)
  103. * @param type 坦克类型
  104. */
  105. public void DrawTank(int x,int y,Graphics g,int direct,int type){
  106. //坦克的类型
  107. switch (type){
  108. case 0: //自己的坦克
  109. g.setColor(Color.CYAN);
  110. break;
  111. case 1: //敌人的坦克
  112. g.setColor(Color.RED);
  113. break;
  114. }
  115. switch (direct){
  116. case 0: //表示向上
  117. g.fill3DRect(x,y,10,60,false); //坦克的左边轮子
  118. g.drawLine(x,y + 10,x + 10,y + 10); //坦克左轮的履带
  119. g.drawLine(x,y + 20,x + 10,y + 20);
  120. g.drawLine(x,y + 30,x + 10,y + 30);
  121. g.drawLine(x,y + 40,x + 10,y + 40);
  122. g.drawLine(x,y + 50,x + 10,y + 50);
  123. g.fill3DRect(x + 40,y,10,60,false); //坦克的右边轮子
  124. g.drawLine(x + 40,y + 10,x + 50,y + 10); //坦克右轮的履带
  125. g.drawLine(x + 40,y + 20,x + 50,y + 20);
  126. g.drawLine(x + 40,y + 30,x + 50,y + 30);
  127. g.drawLine(x + 40,y + 40,x + 50,y + 40);
  128. g.drawLine(x + 40,y + 50,x + 50,y + 50);
  129. g.fill3DRect(x + 10,y + 10,30,40,false); //坦克的身体
  130. g.fillOval(x + 10,y + 15,30,30); //坦克的炮盖
  131. g.drawLine(x + 25,y + 30,x + 25,y); //坦克的炮筒
  132. break;
  133. case 1: //表示向右
  134. g.fill3DRect(x,y,60,10,false); //坦克左边的轮子
  135. g.drawLine(x + 10,y,x + 10 ,y + 10); //坦克左轮的履带
  136. g.drawLine(x + 20,y,x + 20 ,y + 10);
  137. g.drawLine(x + 30,y,x + 30 ,y + 10);
  138. g.drawLine(x + 40,y,x + 40 ,y + 10);
  139. g.drawLine(x + 50,y,x + 50 ,y + 10);
  140. g.fill3DRect(x,y + 40,60,10,false); //坦克右边的轮子
  141. g.drawLine(x + 10,y + 40,x + 10,y + 50);
  142. g.drawLine(x + 20,y + 40,x + 20,y + 50);
  143. g.drawLine(x + 30,y + 40,x + 30,y + 50);
  144. g.drawLine(x + 40,y + 40,x + 40,y + 50);
  145. g.drawLine(x + 50,y + 40,x + 50,y + 50);
  146. g.fill3DRect( x + 10,y + 10,40,30,false); //坦克的身体
  147. g.fillOval(x + 15,y + 10,30,30); //坦克的炮盖
  148. g.drawLine(x + 30,y + 25,x +60,y + 25); //坦克的炮筒
  149. break;
  150. case 2: //表示向下
  151. g.fill3DRect(x,y,10,60,false); //坦克的左边轮子
  152. g.drawLine(x,y + 10,x + 10,y + 10); //坦克左轮的履带
  153. g.drawLine(x,y + 20,x + 10,y + 20);
  154. g.drawLine(x,y + 30,x + 10,y + 30);
  155. g.drawLine(x,y + 40,x + 10,y + 40);
  156. g.drawLine(x,y + 50,x + 10,y + 50);
  157. g.fill3DRect(x + 40,y,10,60,false); //坦克的右边轮子
  158. g.drawLine(x + 40,y + 10,x + 50,y + 10); //坦克右轮的履带
  159. g.drawLine(x + 40,y + 20,x + 50,y + 20);
  160. g.drawLine(x + 40,y + 30,x + 50,y + 30);
  161. g.drawLine(x + 40,y + 40,x + 50,y + 40);
  162. g.drawLine(x + 40,y + 50,x + 50,y + 50);
  163. g.fill3DRect(x + 10,y + 10,30,40,false); //坦克的身体
  164. g.fillOval(x + 10,y + 15,30,30); //坦克的炮盖
  165. g.drawLine(x + 25,y + 30,x + 25,y + 60); //坦克的炮筒
  166. break;
  167. case 3: //表示向左
  168. g.fill3DRect(x,y,60,10,false); //坦克左边的轮子
  169. g.drawLine(x + 10,y,x + 10 ,y + 10); //坦克左轮的履带
  170. g.drawLine(x + 20,y,x + 20 ,y + 10);
  171. g.drawLine(x + 30,y,x + 30 ,y + 10);
  172. g.drawLine(x + 40,y,x + 40 ,y + 10);
  173. g.drawLine(x + 50,y,x + 50 ,y + 10);
  174. g.fill3DRect(x,y + 40,60,10,false); //坦克右边的轮子
  175. g.drawLine(x + 10,y + 40,x + 10,y + 50);
  176. g.drawLine(x + 20,y + 40,x + 20,y + 50);
  177. g.drawLine(x + 30,y + 40,x + 30,y + 50);
  178. g.drawLine(x + 40,y + 40,x + 40,y + 50);
  179. g.drawLine(x + 50,y + 40,x + 50,y + 50);
  180. g.fill3DRect( x + 10,y + 10,40,30,false); //坦克的身体
  181. g.fillOval(x + 15,y + 10,30,30); //坦克的炮盖
  182. g.drawLine(x + 30,y + 25,x,y + 25); //坦克的炮筒
  183. break;
  184. default:
  185. System.out.println("暂时没有处理");
  186. }
  187. }
  188. @Override
  189. public void keyTyped(KeyEvent e) {
  190. }
  191. @Override
  192. public void keyPressed(KeyEvent e) { //控制键盘WDSA键,操控我的坦克上右下左移动
  193. if(e.getKeyCode() == KeyEvent.VK_W){
  194. myTank.setDirect(0);
  195. if(myTank.getY() > 0) {
  196. myTank.MoveUp();
  197. }
  198. }else if(e.getKeyCode() == KeyEvent.VK_D){
  199. myTank.setDirect(1);
  200. if(myTank.getX() + 60 < 1000) {
  201. myTank.MoveRight();
  202. }
  203. }else if(e.getKeyCode() == KeyEvent.VK_S){
  204. myTank.setDirect(2);
  205. if(myTank.getY() + 60 < 800) {
  206. myTank.MoveDown();
  207. }
  208. }else if(e.getKeyCode() == KeyEvent.VK_A){
  209. myTank.setDirect(3);
  210. if(myTank.getX() + 60 > 0) {
  211. myTank.MoveLeft();
  212. }
  213. }
  214. // else if(e.getKeyCode() == KeyEvent.VK_UP){
  215. // opTanks.get(0).setDirect(0);
  216. // opTanks.get(0).MoveUp();
  217. // }else if(e.getKeyCode() == KeyEvent.VK_RIGHT){
  218. // opTanks.get(0).setDirect(1);
  219. // opTanks.get(0).MoveRight();
  220. // }else if(e.getKeyCode() == KeyEvent.VK_DOWN){
  221. // opTanks.get(0).setDirect(2);
  222. // opTanks.get(0).MoveDown();
  223. // }else if(e.getKeyCode() == KeyEvent.VK_LEFT) {
  224. // opTanks.get(0).setDirect(3);
  225. // opTanks.get(0).MoveLeft();
  226. // }
  227. //如果玩家按下J键,我的坦克就会发出一个炮弹
  228. if(e.getKeyCode() == KeyEvent.VK_J){
  229. // System.out.println("玩家按下了J键,开始射击!");
  230. // if(myTank.shot == null || myTank.shot.isLive == false) { //当坦克只能发射一颗炮弹时,先判断
  231. // myTank.shotOpTank();
  232. // }
  233. myTank.shotOpTank();
  234. }
  235. this.repaint();
  236. }
  237. @Override
  238. public void keyReleased(KeyEvent e) {
  239. }
  240. @Override
  241. public void run() {
  242. while(true) {
  243. try {
  244. Thread.sleep(100);
  245. } catch (InterruptedException e) {
  246. e.printStackTrace();
  247. }
  248. //判断是否击中了敌人的坦克
  249. for(int j=0;j<myTank.shots.size();j++) {
  250. if (myTank.shots.get(j) != null && myTank.shots.get(j).isLive) {
  251. for (int i = 0; i < opTanks.size(); i++) { //遍历敌人的所有坦克
  252. HitTank(myTank.shots.get(j), opTanks.get(i));
  253. }
  254. }
  255. }
  256. HitMyTank();
  257. this.repaint();
  258. }
  259. }
  260. //编写方法判断敌方坦克的炮弹是否打中我的坦克
  261. public void HitMyTank(){
  262. for(int i=0;i<opTanks.size();i++){
  263. for(int j=0;j<opTanks.get(i).shots.size();j++){
  264. if(myTank.isLive && opTanks.get(i).shots.get(j).isLive){
  265. HitTank(opTanks.get(i).shots.get(j),myTank);
  266. }
  267. }
  268. }
  269. }
  270. //编写方法判断炮弹是否打中坦克
  271. public void HitTank(Shot s,Tank opTank){
  272. //判断是否击中坦克
  273. switch (opTank.getDirect()){
  274. case 0: //敌人坦克向上的方向
  275. case 2: //敌人坦克向下的方向
  276. if(s.x > opTank.getX() && s.x < opTank.getX() + 50 && s.y > opTank.getY() && s.y < opTank.getY() + 60){
  277. s.isLive = false;
  278. opTank.isLive = false;
  279. //当坦克被击中后将坦克从集合中移除
  280. opTanks.remove(opTank);
  281. //解读,因为opTank可以是没有Tank,也可以是opTank
  282. if(opTank instanceof OpTank){
  283. Recorder.addAllOpTanksNum();
  284. }
  285. }
  286. break;
  287. case 1: //敌人坦克向右的方向
  288. case 3: //敌人坦克向左的方向
  289. if(s.x > opTank.getX() && s.x < opTank.getX() + 60 && s.y > opTank.getY() && s.y < opTank.getY() + 50){
  290. s.isLive = false;
  291. opTank.isLive = false;
  292. //当坦克被击中后将坦克从集合中移除
  293. opTanks.remove(opTank);
  294. //解读,因为opTank可以是没有Tank,也可以是opTank
  295. if(opTank instanceof OpTank){
  296. Recorder.addAllOpTanksNum();
  297. }
  298. }
  299. break;
  300. }
  301. }
  302. }

3.坦克基类(Tank)

  1. package com.wak.TankGame01Version;
  2. /*坦克的基类*/
  3. public class Tank {
  4. private int x; //坦克的横坐标
  5. private int y; //坦克的纵坐标
  6. private int direct = 0; //坦克的方向
  7. private int speed = 1; //坦克的速度
  8. boolean isLive = true; //坦克的存活状态
  9. public Tank(){
  10. this.x = 100; //默认坦克的初始x坐标为100
  11. this.y = 100; //默认坦克的初始y坐标为100
  12. }
  13. public Tank(int x,int y){ //自己设置坦克的初始x,y坐标
  14. this.x = x;
  15. this.y = y;
  16. }
  17. //设置坦克的x坐标
  18. public void setX(int x){
  19. this.x = x;
  20. }
  21. //设置坦克的y坐标
  22. public void setY(int y){
  23. this.y = y;
  24. }
  25. //获得坦克的x坐标
  26. public int getX(){
  27. return x;
  28. }
  29. //获得坦克的y坐标
  30. public int getY(){
  31. return y;
  32. }
  33. //设置坦克的方向
  34. public void setDirect(int direct){
  35. this.direct = direct;
  36. }
  37. //获得坦克的方向
  38. public int getDirect(){
  39. return direct;
  40. }
  41. //设置坦克的速度
  42. public void setSpeed(int speed){
  43. this.speed = speed;
  44. }
  45. //获得坦克的速度
  46. public int getSpeed(){
  47. return speed;
  48. }
  49. //坦克的上右下左移动
  50. public void MoveUp(){
  51. y -= speed;
  52. }
  53. public void MoveRight(){
  54. x += speed;
  55. }
  56. public void MoveDown(){
  57. y += speed;
  58. }
  59. public void MoveLeft(){
  60. x -= speed;
  61. }
  62. }

4.我的坦克类(MyTank)

  1. package com.wak.TankGame01Version;
  2. import java.util.Vector;
  3. /*自己的坦克*/
  4. public class MyTank extends Tank{
  5. //创建一个坦克
  6. private MyTank myTank = null;
  7. //定义一个shot对象,表示一个射击(线程)
  8. Shot shot = null;
  9. //创建一个存储炮弹的集合
  10. Vector<Shot> shots = new Vector<>();
  11. //设置坦克的初始化坐标
  12. public MyTank(int x,int y){
  13. this.setX(x);
  14. this.setY(y);
  15. }
  16. //射击
  17. public void shotOpTank(){
  18. //设置炮弹的初始化坐标及方向
  19. if(shots.size() < 5) {
  20. switch (this.getDirect()) {
  21. case 0:
  22. shot = new Shot(this.getX() + 25, this.getY(), 0);
  23. break;
  24. case 1:
  25. shot = new Shot(this.getX() + 60, this.getY() + 25, 1);
  26. break;
  27. case 2:
  28. shot = new Shot(this.getX() + 25, this.getY() + 60, 2);
  29. break;
  30. case 3:
  31. shot = new Shot(this.getX(), this.getY() + 25, 3);
  32. }
  33. //将发射的炮弹弹存入集合中
  34. shots.add(shot);
  35. }
  36. //启动我们的Shot线程
  37. new Thread(shot).start();
  38. }
  39. }

5.敌方坦克类(OpTank)

  1. package com.wak.TankGame01Version;
  2. import java.util.Vector;
  3. public class OpTank extends Tank implements Runnable{
  4. private OpTank opTank = null; //创建一个敌方坦克
  5. Vector<Shot> shots = new Vector<>(); //存储多个炮弹
  6. Vector<OpTank> opTanks = new Vector<>(); //增加成员,可以得到敌人坦克的Vector集合
  7. public OpTank(int x,int y){
  8. this.setX(x);
  9. this.setY(y);
  10. }
  11. public void setOpTanks(Vector<OpTank> opTanks){
  12. this.opTanks = opTanks;
  13. }
  14. public boolean isTouchOpTank(){
  15. //判断当前敌人坦克的方向
  16. switch (this.getDirect()){
  17. case 0: //上
  18. for(int j=0;j<opTanks.size();j++){
  19. //取出一个敌方坦克
  20. OpTank o = opTanks.get(j);
  21. if(o != this){ //不能跟自己比
  22. //如果敌人是向上或者向下
  23. if(o.getDirect() == 0 || o.getDirect() == 2){
  24. //当前坦克左上角的坐标
  25. if(this.getX() >= o.getX()
  26. && this.getX() <= o.getX() + 50
  27. && this.getY() <= o.getY() + 60
  28. && this.getY() >= o.getY()){
  29. return true;
  30. }
  31. //当前坦克右上角的坐标
  32. if(this.getX() + 50 >= o.getX()
  33. && this.getX() + 50<= o.getX() + 50
  34. && this.getY() <= o.getY() + 60
  35. && this.getY() >= o.getY()){
  36. return true;
  37. }
  38. }
  39. //如果敌人是向右或者向左
  40. if(o.getDirect() == 1 || o.getDirect() == 3){
  41. //当前坦克左上角的坐标
  42. if(this.getX() >= o.getX()
  43. && this.getX() <= o.getX() + 60
  44. && this.getY() >= o.getY()
  45. && this.getY() <= o.getY() + 50){
  46. return true;
  47. }
  48. //当前坦克右上角的坐标
  49. if(this.getX() + 50>= o.getX()
  50. && this.getX() + 50<= o.getX() + 60
  51. && this.getY() >= o.getY()
  52. && this.getY() <= o.getY() + 50){
  53. return true;
  54. }
  55. }
  56. }
  57. }
  58. break;
  59. case 1: //右
  60. for(int j=0;j<opTanks.size();j++){
  61. //取出一辆坦克
  62. OpTank o = opTanks.get(j);
  63. if(o != this){ //不能跟自己比
  64. //如果敌方坦克是向上或向下
  65. if(o.getDirect() == 0 || o.getDirect() == 2){
  66. //当前坦克右上角的坐标
  67. if(this.getX() + 60 >= o.getX()
  68. && this.getX() + 60 <= o.getX() + 50
  69. && this.getY() >= o.getY()
  70. && this.getY() <= o.getY() + 60){
  71. return true;
  72. }
  73. //当前坦克右下角的坐标
  74. if(this.getX() + 60 >= o.getX()
  75. && this.getX() + 60 <= o.getX() + 50
  76. && this.getY() + 50 >= o.getY()
  77. && this.getY() + 50 <= o.getY() + 60){
  78. return true;
  79. }
  80. }
  81. //如果敌方坦克是向右或向左
  82. if(o.getDirect() == 1 || o.getDirect() == 3){
  83. //当前坦克右上角的坐标
  84. if(this.getX() + 60 >= o.getX()
  85. && this.getX() + 60 <= o.getX() + 60
  86. && this.getY() >= o.getY()
  87. && this.getY() <= o.getY() + 50){
  88. return true;
  89. }
  90. //当前坦克右下角的坐标
  91. if(this.getX() + 60 >= o.getX()
  92. && this.getX() + 60 <= o.getX() + 60
  93. && this.getY() + 50 >= o.getY()
  94. && this.getY() + 50 <= o.getY() + 50){
  95. return true;
  96. }
  97. }
  98. }
  99. }
  100. break;
  101. case 2: //下
  102. for(int j=0;j<opTanks.size();j++){
  103. //取出一辆坦克
  104. OpTank o = opTanks.get(j);
  105. if(o != this){ //不能跟自己比
  106. //如果敌方坦克是向上或向下
  107. if(o.getDirect() == 0 || o.getDirect() == 2){
  108. //当前坦克左下角的坐标
  109. if(this.getX() >= o.getX()
  110. && this.getX() <= o.getX() + 60
  111. && this.getY() + 60 >= o.getY()
  112. && this.getY() + 60 <= o.getY()){
  113. return true;
  114. }
  115. //当前坦克右下角的坐标
  116. if(this.getX() + 50>= o.getX()
  117. && this.getX() + 50 <= o.getX() + 60
  118. && this.getY() + 60 >= o.getY()
  119. && this.getY() + 60 <= o.getY()){
  120. return true;
  121. }
  122. }
  123. //如果敌方坦克是向右或向左
  124. if(o.getDirect() == 1 || o.getDirect() == 3){
  125. //当前坦克左下角的坐标
  126. if(this.getX() >= o.getX()
  127. && this.getX() + 60 <= o.getX() + 60
  128. && this.getY() >= o.getY()
  129. && this.getY() + 50 <= o.getY() + 50){
  130. return true;
  131. }
  132. //当前坦克右下角的坐标
  133. if(this.getX() + 50 >= o.getX()
  134. && this.getX() + 50 <= o.getX() + 60
  135. && this.getY() + 60 >= o.getY()
  136. && this.getY() + 60 <= o.getY() + 50){
  137. return true;
  138. }
  139. }
  140. }
  141. }
  142. break;
  143. case 3: //左
  144. for(int j=0;j<opTanks.size();j++){
  145. //取出一辆坦克
  146. OpTank o = opTanks.get(j);
  147. if(o != this){ //不能跟自己比
  148. //如果敌方坦克是向上或向下
  149. if(o.getDirect() == 0 || o.getDirect() == 2){
  150. //当前坦克左上角的坐标
  151. if(this.getX() >= o.getX()
  152. && this.getX() <= o.getX() + 60
  153. && this.getY() >= o.getY()
  154. && this.getY() <= o.getY()){
  155. return true;
  156. }
  157. //当前坦克左下角的坐标
  158. if(this.getX() >= o.getX()
  159. && this.getX() <= o.getX() + 60
  160. && this.getY() + 50 >= o.getY()
  161. && this.getY() + 50 <= o.getY()){
  162. return true;
  163. }
  164. }
  165. //如果敌方坦克是向右或向左
  166. if(o.getDirect() == 1 || o.getDirect() == 3){
  167. //当前坦克左上角的坐标
  168. if(this.getX() >= o.getX()
  169. && this.getX() <= o.getX() + 60
  170. && this.getY() >= o.getY()
  171. && this.getY() <= o.getY() + 50){
  172. return true;
  173. }
  174. //当前坦克左下角的坐标
  175. if(this.getX() >= o.getX()
  176. && this.getX() <= o.getX() + 60
  177. && this.getY() + 50 >= o.getY()
  178. && this.getY() + 50 <= o.getY() + 50){
  179. return true;
  180. }
  181. }
  182. }
  183. }
  184. break;
  185. }
  186. return false;
  187. }
  188. @Override
  189. public void run() {
  190. while(true){
  191. //这里判断坦克的方向,创建对应的炮弹
  192. if(isLive && shots.size() < 6){
  193. Shot s = null;
  194. switch (getDirect()){
  195. case 0:
  196. s = new Shot(getX() + 25,getY(),0);
  197. break;
  198. case 1:
  199. s = new Shot(getX() + 60,getY() + 25,1);
  200. break;
  201. case 2:
  202. s = new Shot(getX() + 25,getY() + 60,2);
  203. break;
  204. case 3:
  205. s = new Shot(getX(),getY() + 25,3);
  206. break;
  207. }
  208. //每隔1秒发射一个炮弹
  209. try {
  210. Thread.sleep(2000);
  211. } catch (InterruptedException e) {
  212. e.printStackTrace();
  213. }
  214. shots.add(s);
  215. new Thread(s).start();
  216. }
  217. //坦克移动的方向
  218. switch (this.getDirect()){
  219. case 0:
  220. for(int i=0;i<80;i++) {
  221. if (getY() > 0 && !isTouchOpTank()){
  222. MoveUp();
  223. }
  224. //休眠
  225. try {
  226. Thread.sleep(50);
  227. } catch (InterruptedException e) {
  228. e.printStackTrace();
  229. }
  230. }
  231. break;
  232. case 1:
  233. for (int i=0;i<80;i++){
  234. if(getX() + 60< 1000 && !isTouchOpTank()) {
  235. MoveRight();
  236. }
  237. //休眠
  238. try {
  239. Thread.sleep(50);
  240. } catch (InterruptedException e) {
  241. e.printStackTrace();
  242. }
  243. }
  244. break;
  245. case 2:
  246. for (int i=0;i<80;i++){
  247. if(getY() + 60 < 800 && !isTouchOpTank()) {
  248. MoveDown();
  249. }
  250. //休眠
  251. try {
  252. Thread.sleep(50);
  253. } catch (InterruptedException e) {
  254. e.printStackTrace();
  255. }
  256. }
  257. break;
  258. case 3:
  259. for (int i=0;i<80;i++){
  260. if(getX() > 0 && !isTouchOpTank()) {
  261. MoveLeft();
  262. }
  263. //休眠
  264. try {
  265. Thread.sleep(50);
  266. } catch (InterruptedException e) {
  267. e.printStackTrace();
  268. }
  269. }
  270. break;
  271. }
  272. setDirect((int)(Math.random() * 4));
  273. if(!isLive){
  274. break;
  275. }
  276. }
  277. }
  278. }

6.炮弹类(Shot)

  1. package com.wak.TankGame01Version;
  2. public class Shot implements Runnable{
  3. int x; //子弹的x坐标
  4. int y; //子弹的y坐标
  5. int direct = 0; //子弹的方向
  6. int speed = 2; //子弹的速度
  7. boolean isLive = true; //子弹的存活状态
  8. public Shot(int x,int y,int direct){
  9. this.x = x;
  10. this.y = y;
  11. this.direct = direct;
  12. }
  13. @Override
  14. public void run() { //射击
  15. while(isLive){
  16. //休眠
  17. try {
  18. Thread.sleep(50);
  19. } catch (InterruptedException e) {
  20. e.printStackTrace();
  21. }
  22. switch (direct){
  23. case 0: //向上
  24. y -= speed;
  25. break;
  26. case 1: //向右
  27. x += speed;
  28. break;
  29. case 2: //向下
  30. y += speed;
  31. break;
  32. case 3: //向左
  33. x -= speed;
  34. break;
  35. }
  36. System.out.println("炮弹的x坐标:" + x + ",炮弹的y坐标:" + y);
  37. //如果炮弹弹撞到墙壁,则销毁
  38. //当炮弹碰到敌人坦克时,也应当结束
  39. if(!(x >= 0 && x <= 1000 && y >=0 && y <= 800 && isLive)){
  40. isLive = false;
  41. System.out.println("炮弹已销毁");
  42. }
  43. }
  44. }
  45. }

7.记录信息类(Recorder)

  1. package com.wak.TankGame01Version;
  2. import java.awt.*;
  3. import java.io.*;
  4. import java.util.Vector;
  5. public class Recorder {
  6. private static int allOpTanksNum = 0;
  7. //定义IO对象,准备写数据到文件中
  8. private static FileWriter fw = null;
  9. private static BufferedWriter bw = null;
  10. private static BufferedReader br = null;
  11. private static String recordFile = "D:\\myTankGameRecord.txt";
  12. //定义Vec,指向GamePanel对象的 敌人坦克Vector
  13. private static Vector<OpTank> opTanks = null;
  14. //定义一个Node 的Vector,用于保存敌人的信息node
  15. private static Vector<Node> nodes = new Vector<>();
  16. public static void setOpTanks(Vector<OpTank> opTanks){
  17. Recorder.opTanks = opTanks;
  18. }
  19. public static int getAllOpTanksNum(){
  20. return allOpTanksNum;
  21. }
  22. public static void setAllOpTanksNum(int allOpTanksNum){
  23. Recorder.allOpTanksNum = allOpTanksNum;
  24. }
  25. //当我方坦克击毁一个敌人坦克,就应当allOpTanksNum++
  26. public static void addAllOpTanksNum(){
  27. Recorder.allOpTanksNum++;
  28. }
  29. //增加一个方法,当游戏退出时,我们将allOpTanksNum保存到recordFile
  30. //对KeepRecord方法进行升级,保存敌人坦克的坐标和方向
  31. public static void KeepRecord(){
  32. try {
  33. bw = new BufferedWriter((new FileWriter((recordFile))));
  34. bw.write(allOpTanksNum + "\r\n");
  35. //遍历敌人坦克的Vector,然后根据情况保存即可
  36. for(int i=0;i<opTanks.size();i++){
  37. //取出敌人坦克
  38. OpTank o = opTanks.get(i);
  39. if(o.isLive){
  40. //保存该opTank的信息
  41. String record = o.getX() + " " + o.getY() + " " + o.getDirect();
  42. //写入到文件
  43. bw.write(record + "\r\n");
  44. }
  45. }
  46. } catch (IOException e) {
  47. e.printStackTrace();
  48. }finally {
  49. if (bw != null) {
  50. try {
  51. bw.close();
  52. } catch (IOException e) {
  53. e.printStackTrace();
  54. }
  55. }
  56. }
  57. }
  58. // //增加一个方法,用于读取recordFile,恢复相关信息
  59. // public static Vector<Node> getNodesAndEnemyTankRec(){
  60. // try {
  61. // br = new BufferedReader(new FileReader(recordFile));
  62. //
  63. // } catch (FileNotFoundException e) {
  64. // e.printStackTrace();
  65. // }finally {
  66. //
  67. // }
  68. // return null;
  69. // }
  70. }

运行效果截图:

阶段四:

小总结:今天完成了界面画面的布置,包括画了一条小河,草地,和障碍物(墙体),以及坦克碰到障碍物会停止前进,炮弹打到墙壁会销毁。今天真的是写这个项目这么久来,让我最印象深刻的一次今天,我在写完障碍物,遇到一个问题(当时没有截图或者录视频保存下来,可惜的是),就是我在离界面顶部Y坐标为100的位置时,坦克只会在这个Y坐标为0到100的范围内移动,于是我就觉得很奇怪,然后我就强制让他们只能朝下移动,结果发现,到了Y坐标等于100这个线的时候,所有的坦克全都不动了,只是发射炮弹,不会再继续往下移动。我又重新看了一遍我的方法,没有问题,于是我只好找学长求助,因为当我让他们自由可以改变方向移动时,他们能突破Y坐标为100的这条我暂且称之为“诡异线”,因为学长们对我的代码也不是特别熟悉,所以他们也没有给出一个正确答案,然后我就去找我之前的大四室友(已经在苏宁易购工作了),在通过测试时,我们发现一个问题,因为我是设置的六个坦克,从左到右依次排开,初始化他们是先向下移动的,当移动完之后,有一个坦克正好碰到了障碍物,而其他的没有,于是我们就猜测是不是这个影响了其他坦克,于是我们就把这个前面是障碍物的坦克删除掉,但是还是不行,我们最后只测试一个,发现这个坦克就可以突破这个“诡异线”,于是我想到了,就算把那个正好碰到坦克的障碍物删除,但是有一个坦克的右下角,与障碍物的一个角挨着了,因为我的判断是够与墙壁碰撞的判断条件,是写的大于等于,或者小于等于,就是这个等号,让代码运行过程有问题,后来总结出,尤其是在写这种游戏时,有的边界条件不能卡的太死,要不然就会出问题,因为这个毕竟是像素块,说不定就有个时候,越过了这个边界,然后就卡住了。但是由于是第一次写,还有很多知识点没有完全掌握好,所以当解决完这个问题后,整个人真的是,或许这就是代码的魅力吧!

以下是今天的代码记录截图:

七个类(根据英文应该能猜到各自对应什么)

 

1.主程序类(TankGame01)

  1. package com.wak.TankGame01Version;
  2. import javax.swing.*;
  3. import java.awt.event.WindowAdapter;
  4. import java.awt.event.WindowEvent;
  5. /*坦克大战游戏主程序*/
  6. public class TankGame01 extends JFrame {
  7. public static void main(String[] args) {
  8. //启动!
  9. new TankGame01();
  10. }
  11. //定义GamePanel,创建游戏环境
  12. GamePanel gamePanel = null;
  13. //加载游戏环境
  14. public TankGame01(){
  15. //1.0版本
  16. this.setTitle("坦克大战1.0");
  17. //加载游戏环境
  18. gamePanel = new GamePanel();
  19. //将游戏区域加载到界面里
  20. this.add(gamePanel);
  21. //将游戏界面的炮弹线程加入到界面里
  22. Thread thread = new Thread(gamePanel);
  23. //启动子线程
  24. thread.start();
  25. //将键盘监听器加载到界面里
  26. this.addKeyListener(gamePanel);
  27. //设置界面可视化
  28. this.setVisible(true);
  29. //设置界面的大小
  30. this.setSize(1600,950);
  31. //设置界面可关闭
  32. this.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
  33. //在JFrame中增加相应关闭窗口的处理
  34. this.addWindowListener(new WindowAdapter() {
  35. @Override
  36. public void windowClosing(WindowEvent e) {
  37. Recorder.KeepRecord();
  38. System.exit(0);
  39. }
  40. });
  41. }
  42. }

 

2.游戏界面绘制类(GamePanel)

  1. package com.wak.TankGame01Version;
  2. import javax.swing.*;
  3. import java.awt.*;
  4. import java.awt.event.KeyEvent;
  5. import java.awt.event.KeyListener;
  6. import java.util.Vector;
  7. /*坦克大战的绘图区域*/
  8. //为了监听键盘事件,实现KeyListener
  9. //
  10. public class GamePanel extends JPanel implements KeyListener,Runnable{
  11. //定义一个自己的坦克
  12. MyTank myTank = null;
  13. //创建敌方坦克
  14. Vector<OpTank> opTanks = new Vector<>();
  15. //定义一个存放Node对象的Vector,用于恢复敌方坦克的坐标和方向
  16. Vector<Node> nodes = new Vector<>();
  17. //设置敌方坦克数量
  18. int opTanksSize = 6;
  19. public GamePanel(/*String key*/){
  20. // Recorder.getNodesAndEnemyTankRec();
  21. myTank = new MyTank(580,810); //初始化我的坦克的位置
  22. myTank.setSpeed(3); //设置我的坦克的速度
  23. // myTank.shot.setShotSpeed(5); //设置我的坦克的炮弹的速度
  24. //将GamePanel对象的 opTanks 设置给 Recorder 的 opTanks
  25. Recorder.setOpTanks(opTanks);
  26. //初始化敌方坦克
  27. for(int i=0;i<opTanksSize;i++){
  28. OpTank opTank = new OpTank((200 * i + 90),0);
  29. opTank.setOpTanks(opTanks);
  30. //设置方向
  31. opTank.setDirect(2);
  32. //设置敌人坦克的速度
  33. opTank.setSpeed(1);
  34. //启动敌人坦克线程
  35. new Thread(opTank).start();
  36. //给该opTank加入一颗炮弹
  37. Shot shot = new Shot(opTank.getX() + 25,opTank.getY() + 60,2);
  38. //存放到Vector中
  39. opTank.shots.add(shot);
  40. //启动线程对象
  41. new Thread(shot).start();
  42. //加入
  43. opTanks.add(opTank);
  44. }
  45. }
  46. //编写方法,显示我方击毁敌方坦克的信息
  47. public void showInfo(Graphics g){
  48. //画出玩家的总成绩
  49. g.setColor(Color.BLACK);
  50. Font font = new Font("宋体",Font.BOLD,25);
  51. g.setFont(font);
  52. g.drawString("您累计击毁敌方坦克的数量",1220,30);
  53. DrawTank(1220,60,g,0,1);
  54. g.setColor(Color.BLACK);
  55. g.drawString(Recorder.getAllOpTanksNum() + "",1280,100);
  56. }
  57. @Override
  58. public void paint(Graphics g) {
  59. super.paint(g);
  60. g.fillRect(0,0,1200,900); //默认背景是黑色
  61. //设置背景为蓝色,代表河流
  62. g.setColor(Color.cyan);
  63. g.fill3DRect(100,400,1000,200,false);
  64. //设置背景为绿色,代表草地
  65. g.setColor(Color.GREEN);
  66. for(int i=0;i<7;i++) {
  67. g.fill3DRect(15 * i,100,5,600,false);
  68. g.fill3DRect(1100 + 15 * i,100,5,600,false);
  69. }
  70. for(int i=0;i<41;i++) {
  71. g.fill3DRect(0,100 + 15 * i,95,5,false);
  72. g.fill3DRect(1100,100 + 15 * i,95,5,false);
  73. }
  74. //设置背景为亮灰色,代表墙体
  75. g.setColor(Color.LIGHT_GRAY);
  76. g.fill3DRect(500,660,200,50,false);
  77. for(int i=1;i<5;i++) {
  78. g.drawLine(500, 660 + i*10, 700, 660 + i*10);
  79. }
  80. for(int i=1;i<20;i++){
  81. g.drawLine(500 + i*10,660,500 + i*10,710);
  82. }
  83. g.fill3DRect(260,660,60,130,false);
  84. for(int i=1;i<6;i++){
  85. g.drawLine(260 + i*10,660,260 + i*10,790);
  86. }
  87. for(int i=1;i<13;i++){
  88. g.drawLine(260,660 + i*10,320,660 + i*10);
  89. }
  90. g.fill3DRect(880,660,60,130,false);
  91. for(int i=1;i<6;i++){
  92. g.drawLine(880 + i*10,660,880 + i*10,790);
  93. }
  94. for(int i=1;i<13;i++){
  95. g.drawLine(880,660 + i*10,940,660 + i*10);
  96. }
  97. g.fill3DRect(350,100,60,240,false);
  98. for(int i=1;i<6;i++){
  99. g.drawLine(350 + i*10,100,350 + i*10,340);
  100. }
  101. for(int i=1;i<24;i++){
  102. g.drawLine(350,100 + i*10,410,100 + i*10);
  103. }
  104. g.fill3DRect(790,100,60,240,false);
  105. for(int i=1;i<6;i++){
  106. g.drawLine(790 + i*10,100,790 + i*10,340);
  107. }
  108. for(int i=1;i<24;i++){
  109. g.drawLine(790,100 + i*10,850,100 + i*10);
  110. }
  111. g.fill3DRect(550,160,100,100,false);
  112. for(int i=1;i<10;i++){
  113. g.drawLine(550 + i*10,160 ,550 + i*10,260);
  114. }
  115. for(int i=1;i<10;i++){
  116. g.drawLine(550,160 + i*10,650,160 + i*10);
  117. }
  118. // g.fill3DRect(160,100,130,60,false);
  119. // for(int i=1;i<13;i++){
  120. // g.drawLine(160 + i*10,100,160 + i*10,160);
  121. // }
  122. // for(int i=1;i<6;i++){
  123. // g.drawLine(160,100 + i*10,290,100 + i*10);
  124. // }
  125. // g.fill3DRect(910,100,130,60,false);
  126. // for(int i=1;i<13;i++){
  127. // g.drawLine(910 + i*10,100,910 + i*10,160);
  128. // }
  129. // for(int i=1;i<6;i++){
  130. // g.drawLine(910,100 + i*10,1040,100 + i*10);
  131. // }
  132. showInfo(g);
  133. //画出坦克-封装方法
  134. //画出我的坦克
  135. if(myTank.isLive) {
  136. DrawTank(myTank.getX(), myTank.getY(), g, myTank.getDirect(), 0);
  137. }
  138. //画出敌人的坦克
  139. for(int i=0;i<opTanks.size();i++){
  140. //取出敌方坦克
  141. OpTank opTank = opTanks.get(i);
  142. //判断敌方坦克是否存活
  143. if(opTank.isLive) { //当敌人坦克是存活的时候,才去画
  144. DrawTank(opTank.getX(), opTank.getY(), g, opTank.getDirect(), 1);
  145. //画出敌人的坦克发出的炮弹
  146. for (int j = 0; j < opTank.shots.size(); j++) {
  147. //取出子弹
  148. Shot shot = opTank.shots.get(j);
  149. //绘制
  150. if (shot.isLive) {
  151. g.setColor(Color.RED);
  152. g.fill3DRect(shot.x, shot.y, 4, 4, true);
  153. } else {
  154. opTank.shots.remove(shot);
  155. }
  156. }
  157. }
  158. }
  159. //画出我的坦克发出的炮弹
  160. if(myTank.isLive) {
  161. for (int i = 0; i < myTank.shots.size(); i++) {
  162. if (myTank.shots.get(i) != null && myTank.shots.get(i).isLive == true) {
  163. g.setColor(Color.YELLOW);
  164. g.fill3DRect(myTank.shots.get(i).x, myTank.shots.get(i).y, 4, 4, false);
  165. } else {
  166. myTank.shots.remove(i);
  167. }
  168. }
  169. }
  170. }
  171. //编写方法,画出坦克
  172. /**
  173. *
  174. * @param x 坦克的x坐标
  175. * @param y 坦克的y坐标
  176. * @param g 画笔
  177. * @param direct 坦克方向(上下左右)
  178. * @param type 坦克类型
  179. */
  180. public void DrawTank(int x,int y,Graphics g,int direct,int type){
  181. //坦克的类型
  182. switch (type){
  183. case 0: //自己的坦克
  184. g.setColor(Color.PINK);
  185. break;
  186. case 1: //敌人的坦克
  187. g.setColor(Color.RED);
  188. break;
  189. }
  190. switch (direct){
  191. case 0: //表示向上
  192. g.fill3DRect(x,y,10,60,false); //坦克的左边轮子
  193. g.drawLine(x,y + 10,x + 10,y + 10); //坦克左轮的履带
  194. g.drawLine(x,y + 20,x + 10,y + 20);
  195. g.drawLine(x,y + 30,x + 10,y + 30);
  196. g.drawLine(x,y + 40,x + 10,y + 40);
  197. g.drawLine(x,y + 50,x + 10,y + 50);
  198. g.fill3DRect(x + 40,y,10,60,false); //坦克的右边轮子
  199. g.drawLine(x + 40,y + 10,x + 50,y + 10); //坦克右轮的履带
  200. g.drawLine(x + 40,y + 20,x + 50,y + 20);
  201. g.drawLine(x + 40,y + 30,x + 50,y + 30);
  202. g.drawLine(x + 40,y + 40,x + 50,y + 40);
  203. g.drawLine(x + 40,y + 50,x + 50,y + 50);
  204. g.fill3DRect(x + 10,y + 10,30,40,false); //坦克的身体
  205. g.fillOval(x + 10,y + 15,30,30); //坦克的炮盖
  206. g.drawLine(x + 25,y + 30,x + 25,y); //坦克的炮筒
  207. break;
  208. case 1: //表示向右
  209. g.fill3DRect(x,y,60,10,false); //坦克左边的轮子
  210. g.drawLine(x + 10,y,x + 10 ,y + 10); //坦克左轮的履带
  211. g.drawLine(x + 20,y,x + 20 ,y + 10);
  212. g.drawLine(x + 30,y,x + 30 ,y + 10);
  213. g.drawLine(x + 40,y,x + 40 ,y + 10);
  214. g.drawLine(x + 50,y,x + 50 ,y + 10);
  215. g.fill3DRect(x,y + 40,60,10,false); //坦克右边的轮子
  216. g.drawLine(x + 10,y + 40,x + 10,y + 50);
  217. g.drawLine(x + 20,y + 40,x + 20,y + 50);
  218. g.drawLine(x + 30,y + 40,x + 30,y + 50);
  219. g.drawLine(x + 40,y + 40,x + 40,y + 50);
  220. g.drawLine(x + 50,y + 40,x + 50,y + 50);
  221. g.fill3DRect( x + 10,y + 10,40,30,false); //坦克的身体
  222. g.fillOval(x + 15,y + 10,30,30); //坦克的炮盖
  223. g.drawLine(x + 30,y + 25,x +60,y + 25); //坦克的炮筒
  224. break;
  225. case 2: //表示向下
  226. g.fill3DRect(x,y,10,60,false); //坦克的左边轮子
  227. g.drawLine(x,y + 10,x + 10,y + 10); //坦克左轮的履带
  228. g.drawLine(x,y + 20,x + 10,y + 20);
  229. g.drawLine(x,y + 30,x + 10,y + 30);
  230. g.drawLine(x,y + 40,x + 10,y + 40);
  231. g.drawLine(x,y + 50,x + 10,y + 50);
  232. g.fill3DRect(x + 40,y,10,60,false); //坦克的右边轮子
  233. g.drawLine(x + 40,y + 10,x + 50,y + 10); //坦克右轮的履带
  234. g.drawLine(x + 40,y + 20,x + 50,y + 20);
  235. g.drawLine(x + 40,y + 30,x + 50,y + 30);
  236. g.drawLine(x + 40,y + 40,x + 50,y + 40);
  237. g.drawLine(x + 40,y + 50,x + 50,y + 50);
  238. g.fill3DRect(x + 10,y + 10,30,40,false); //坦克的身体
  239. g.fillOval(x + 10,y + 15,30,30); //坦克的炮盖
  240. g.drawLine(x + 25,y + 30,x + 25,y + 60); //坦克的炮筒
  241. break;
  242. case 3: //表示向左
  243. g.fill3DRect(x,y,60,10,false); //坦克左边的轮子
  244. g.drawLine(x + 10,y,x + 10 ,y + 10); //坦克左轮的履带
  245. g.drawLine(x + 20,y,x + 20 ,y + 10);
  246. g.drawLine(x + 30,y,x + 30 ,y + 10);
  247. g.drawLine(x + 40,y,x + 40 ,y + 10);
  248. g.drawLine(x + 50,y,x + 50 ,y + 10);
  249. g.fill3DRect(x,y + 40,60,10,false); //坦克右边的轮子
  250. g.drawLine(x + 10,y + 40,x + 10,y + 50);
  251. g.drawLine(x + 20,y + 40,x + 20,y + 50);
  252. g.drawLine(x + 30,y + 40,x + 30,y + 50);
  253. g.drawLine(x + 40,y + 40,x + 40,y + 50);
  254. g.drawLine(x + 50,y + 40,x + 50,y + 50);
  255. g.fill3DRect( x + 10,y + 10,40,30,false); //坦克的身体
  256. g.fillOval(x + 15,y + 10,30,30); //坦克的炮盖
  257. g.drawLine(x + 30,y + 25,x,y + 25); //坦克的炮筒
  258. break;
  259. default:
  260. System.out.println("暂时没有处理");
  261. }
  262. }
  263. @Override
  264. public void keyTyped(KeyEvent e) {
  265. }
  266. @Override
  267. public void keyPressed(KeyEvent e) { //控制键盘WDSA键,操控我的坦克上右下左移动
  268. if(e.getKeyCode() == KeyEvent.VK_W){
  269. myTank.setDirect(0);
  270. if(myTank.getY() > 0 && !isMyTankTouchWall()) {
  271. myTank.MoveUp();
  272. }
  273. }else if(e.getKeyCode() == KeyEvent.VK_D){
  274. myTank.setDirect(1);
  275. if(myTank.getX() + 60 < 1200 && !isMyTankTouchWall()) {
  276. myTank.MoveRight();
  277. }
  278. }else if(e.getKeyCode() == KeyEvent.VK_S){
  279. myTank.setDirect(2);
  280. if(myTank.getY() + 60 < 900 && !isMyTankTouchWall()) {
  281. myTank.MoveDown();
  282. }
  283. }else if(e.getKeyCode() == KeyEvent.VK_A){
  284. myTank.setDirect(3);
  285. if(myTank.getX() + 60 > 0 && !isMyTankTouchWall()) {
  286. myTank.MoveLeft();
  287. }
  288. }
  289. // else if(e.getKeyCode() == KeyEvent.VK_UP){
  290. // opTanks.get(0).setDirect(0);
  291. // opTanks.get(0).MoveUp();
  292. // }else if(e.getKeyCode() == KeyEvent.VK_RIGHT){
  293. // opTanks.get(0).setDirect(1);
  294. // opTanks.get(0).MoveRight();
  295. // }else if(e.getKeyCode() == KeyEvent.VK_DOWN){
  296. // opTanks.get(0).setDirect(2);
  297. // opTanks.get(0).MoveDown();
  298. // }else if(e.getKeyCode() == KeyEvent.VK_LEFT) {
  299. // opTanks.get(0).setDirect(3);
  300. // opTanks.get(0).MoveLeft();
  301. // }
  302. //如果玩家按下J键,我的坦克就会发出一个炮弹
  303. if(e.getKeyCode() == KeyEvent.VK_J){
  304. // System.out.println("玩家按下了J键,开始射击!");
  305. // if(myTank.shot == null || myTank.shot.isLive == false) { //当坦克只能发射一颗炮弹时,先判断
  306. // myTank.shotOpTank();
  307. // }
  308. myTank.shotOpTank();
  309. }
  310. this.repaint();
  311. }
  312. @Override
  313. public void keyReleased(KeyEvent e) {
  314. }
  315. @Override
  316. public void run() {
  317. while(true) {
  318. try {
  319. Thread.sleep(100);
  320. } catch (InterruptedException e) {
  321. e.printStackTrace();
  322. }
  323. //判断是否击中了敌人的坦克
  324. for(int j=0;j<myTank.shots.size();j++) {
  325. if (myTank.shots.get(j) != null && myTank.shots.get(j).isLive) {
  326. for (int i = 0; i < opTanks.size(); i++) { //遍历敌人的所有坦克
  327. HitTank(myTank.shots.get(j), opTanks.get(i));
  328. }
  329. }
  330. }
  331. HitMyTank();
  332. this.repaint();
  333. }
  334. }
  335. //编写方法判断敌方坦克的炮弹是否打中我的坦克
  336. public void HitMyTank(){
  337. for(int i=0;i<opTanks.size();i++){
  338. for(int j=0;j<opTanks.get(i).shots.size();j++){
  339. if(myTank.isLive && opTanks.get(i).shots.get(j).isLive){
  340. HitTank(opTanks.get(i).shots.get(j),myTank);
  341. }
  342. }
  343. }
  344. }
  345. //编写方法判断炮弹是否打中坦克
  346. public void HitTank(Shot s,Tank opTank){
  347. //判断是否击中坦克
  348. switch (opTank.getDirect()){
  349. case 0: //敌人坦克向上的方向
  350. case 2: //敌人坦克向下的方向
  351. if(s.x > opTank.getX() && s.x < opTank.getX() + 50 && s.y > opTank.getY() && s.y < opTank.getY() + 60){
  352. s.isLive = false;
  353. opTank.isLive = false;
  354. //当坦克被击中后将坦克从集合中移除
  355. opTanks.remove(opTank);
  356. //解读,因为opTank可以是没有Tank,也可以是opTank
  357. if(opTank instanceof OpTank){
  358. Recorder.addAllOpTanksNum();
  359. }
  360. }
  361. break;
  362. case 1: //敌人坦克向右的方向
  363. case 3: //敌人坦克向左的方向
  364. if(s.x > opTank.getX() && s.x < opTank.getX() + 60 && s.y > opTank.getY() && s.y < opTank.getY() + 50){
  365. s.isLive = false;
  366. opTank.isLive = false;
  367. //当坦克被击中后将坦克从集合中移除
  368. opTanks.remove(opTank);
  369. //解读,因为opTank可以是没有Tank,也可以是opTank
  370. if(opTank instanceof OpTank){
  371. Recorder.addAllOpTanksNum();
  372. }
  373. }
  374. break;
  375. }
  376. }
  377. //判断我方坦克是否触碰到了墙壁
  378. public boolean isMyTankTouchWall(){
  379. //判断敌人当前的方向
  380. switch (myTank.getDirect()){
  381. case 0: //向上
  382. if(myTank.getX() > 500 && myTank.getX() < 700 && myTank.getY() > 660 && myTank.getY() < 710
  383. // || o.getX() > 160 && o.getX() <= 290 && o.getY() > 100 && o.getY() <= 160
  384. // || o.getX() > 910 && o.getX() <= 1040 && o.getY() > 100 && o.getY() <= 160
  385. || myTank.getX() > 550 && myTank.getX() < 650 && myTank.getY() > 160 && myTank.getY() < 260
  386. || myTank.getX() > 790 && myTank.getX() < 850 && myTank.getY() > 100 && myTank.getY() < 160
  387. || myTank.getX() > 350 && myTank.getX() < 410 && myTank.getY() > 100 && myTank.getY() < 340
  388. || myTank.getX() > 880 && myTank.getX() < 940 && myTank.getY() > 660 && myTank.getY() < 790
  389. || myTank.getX() > 260 && myTank.getX() < 320 && myTank.getY() > 660 && myTank.getY() < 790){
  390. return true;
  391. }
  392. //当前坦克的右上角坐标
  393. if(myTank.getX() + 50 > 500 && myTank.getX() + 50 < 700 && myTank.getY() > 660 && myTank.getY() < 710
  394. // || o.getX() + 50 >= 160 && o.getX() + 50 <= 290 && o.getY() >= 100 && o.getY() <= 160
  395. // || o.getX() + 50 >= 910 && o.getX() + 50 <= 1040 && o.getY() >= 100 && o.getY() <= 160
  396. || myTank.getX() + 50 > 550 && myTank.getX() + 50 < 650 && myTank.getY() > 160 && myTank.getY() < 260
  397. || myTank.getX() + 50 > 790 && myTank.getX() + 50 < 850 && myTank.getY() > 100 && myTank.getY() < 160
  398. || myTank.getX() + 50 > 350 && myTank.getX() + 50 < 410 && myTank.getY() > 100 && myTank.getY() < 340
  399. || myTank.getX() + 50 > 880 && myTank.getX() + 50 < 940 && myTank.getY() > 660 && myTank.getY() < 790
  400. || myTank.getX() + 50 > 260 && myTank.getX() + 50 < 320 && myTank.getY() > 660 && myTank.getY() < 790) {
  401. return true;
  402. }
  403. break;
  404. case 1: //向右
  405. //当前坦克的右上角坐标
  406. if (myTank.getX() + 60 > 500 && myTank.getX() + 60 < 700 && myTank.getY() > 660 && myTank.getY() < 710
  407. // || o.getX() + 60 >= 160 && o.getX() + 60 <= 290 && o.getY() >= 100 && o.getY() <= 160
  408. // || o.getX() + 60 >= 910 && o.getX() + 60 <= 1040 && o.getY() >= 100 && o.getY() <= 160
  409. || myTank.getX() + 60 > 550 && myTank.getX() + 60 < 650 && myTank.getY() > 160 && myTank.getY() < 260
  410. || myTank.getX() + 60 > 790 && myTank.getX() + 60 < 850 && myTank.getY() > 100 && myTank.getY() < 160
  411. || myTank.getX() + 60 > 350 && myTank.getX() + 60 < 410 && myTank.getY() > 100 && myTank.getY() < 340
  412. || myTank.getX() + 60 > 880 && myTank.getX() + 60 < 940 && myTank.getY() > 660 && myTank.getY() < 790
  413. || myTank.getX() + 60 > 260 && myTank.getX() + 60 < 320 && myTank.getY() > 660 && myTank.getY() < 790){
  414. return true;
  415. }
  416. //当前坦克的右下角坐标
  417. if(myTank.getX() + 60 > 500 && myTank.getX() + 60 < 700 && myTank.getY() + 50 > 660 && myTank.getY() + 50 < 710
  418. // || o.getX() + 60 >= 160 && o.getX() + 60 <= 290 && o.getY() + 50 >= 100 && o.getY() + 50 <= 160
  419. // || o.getX() + 60 >= 910 && o.getX() + 60 <= 1040 && o.getY() + 50 >= 100 && o.getY() + 50 <= 160
  420. || myTank.getX() + 60 > 550 && myTank.getX() + 60 < 650 && myTank.getY() + 50 > 160 && myTank.getY() + 50 < 260
  421. || myTank.getX() + 60 > 790 && myTank.getX() + 60 < 850 && myTank.getY() + 50 > 100 && myTank.getY() + 50 < 160
  422. || myTank.getX() + 60 > 350 && myTank.getX() + 60 < 410 && myTank.getY() + 50 > 100 && myTank.getY() + 50 < 340
  423. || myTank.getX() + 60 > 880 && myTank.getX() + 60 < 940 && myTank.getY() + 50 > 660 && myTank.getY() + 50 < 790
  424. || myTank.getX() + 60 > 260 && myTank.getX() + 60 < 320 && myTank.getY() + 50 > 660 && myTank.getY() + 50 < 790){
  425. return true;
  426. }
  427. break;
  428. case 2: //向下
  429. //当前坦克的左下角坐标
  430. if(myTank.getX() > 500 && myTank.getX() < 700 && myTank.getY() + 60 > 660 && myTank.getY() + 60 < 710
  431. // || o.getX() >= 160 && o.getX() <= 290 && o.getY() + 60 >= 100 && o.getY() + 60 <= 160
  432. // || o.getX() >= 910 && o.getX() <= 1040 && o.getY() + 60 >= 100 && o.getY() + 60 <= 160
  433. || myTank.getX() > 550 && myTank.getX() < 650 && myTank.getY() + 60 > 160 && myTank.getY() + 60 < 260
  434. || myTank.getX() > 790 && myTank.getX() < 850 && myTank.getY() + 60 > 100 && myTank.getY() + 60 < 160
  435. || myTank.getX() > 350 && myTank.getX() < 410 && myTank.getY() + 60 > 100 && myTank.getY() + 60 < 340
  436. || myTank.getX() > 880 && myTank.getX() < 940 && myTank.getY() + 60 > 660 && myTank.getY() + 60 < 790
  437. || myTank.getX() > 260 && myTank.getX() < 320 && myTank.getY() + 60 > 660 && myTank.getY() + 60 < 790){
  438. return true;
  439. }
  440. //当前坦克的右下角坐标
  441. if(myTank.getX() + 50 > 500 && myTank.getX() + 50 < 700 && myTank.getY() + 60 > 660 && myTank.getY() + 60 < 710
  442. // || o.getX() + 50 >= 160 && o.getX() + 50 <= 290 && o.getY() + 60 >= 100 && o.getY() + 60 <= 160
  443. // || o.getX() + 50 >= 910 && o.getX() + 50 <= 1040 && o.getY() + 60 >= 100 && o.getY() + 60 <= 160
  444. || myTank.getX() + 50 > 550 && myTank.getX() + 50 < 650 && myTank.getY() + 60 > 160 && myTank.getY() + 60 < 260
  445. || myTank.getX() + 50 > 790 && myTank.getX() + 50 < 850 && myTank.getY() + 60 > 100 && myTank.getY() + 60 < 160
  446. || myTank.getX() + 50 > 350 && myTank.getX() + 50 < 410 && myTank.getY() + 60 > 100 && myTank.getY() + 60 < 340
  447. || myTank.getX() + 50 > 880 && myTank.getX() + 50 < 940 && myTank.getY() + 60 > 660 && myTank.getY() + 60 < 790
  448. || myTank.getX() + 50 > 260 && myTank.getX() + 50 < 320 && myTank.getY() + 60 > 660 && myTank.getY() + 60 < 790){
  449. return true;
  450. }
  451. break;
  452. case 3: //向左
  453. //当前坦克的左上角坐标
  454. if(myTank.getX() > 500 && myTank.getX() < 700 && myTank.getY() > 660 && myTank.getY() < 710
  455. // || o.getX() >= 160 && o.getX() <= 290 && o.getY() >= 100 && o.getY() <= 160
  456. // || o.getX() >= 910 && o.getX() <= 1040 && o.getY() >= 100 && o.getY() <= 160
  457. || myTank.getX() > 550 && myTank.getX() < 650 && myTank.getY() > 160 && myTank.getY() < 260
  458. || myTank.getX() > 790 && myTank.getX() < 850 && myTank.getY() > 100 && myTank.getY() < 160
  459. || myTank.getX() > 350 && myTank.getX() < 410 && myTank.getY() > 100 && myTank.getY() < 340
  460. || myTank.getX() > 880 && myTank.getX() < 940 && myTank.getY() > 660 && myTank.getY() < 790
  461. || myTank.getX() > 260 && myTank.getX() < 320 && myTank.getY() > 660 && myTank.getY() < 790){
  462. return true;
  463. }
  464. //当前坦克的左下角坐标
  465. if(myTank.getX() > 500 && myTank.getX() < 700 && myTank.getY() + 50 > 660 && myTank.getY() + 50 < 710
  466. || myTank.getX() > 160 && myTank.getX() < 290 && myTank.getY() + 50 > 100 && myTank.getY() + 50 < 160
  467. || myTank.getX() > 910 && myTank.getX() < 1040 && myTank.getY() + 50 > 100 && myTank.getY() + 50 < 160
  468. || myTank.getX() > 550 && myTank.getX() < 650 && myTank.getY() + 50 > 160 && myTank.getY() + 50 < 260
  469. || myTank.getX() > 790 && myTank.getX() < 850 && myTank.getY() + 50 > 100 && myTank.getY() + 50 < 160
  470. || myTank.getX() > 350 && myTank.getX() < 410 && myTank.getY() + 50 > 100 && myTank.getY() + 50 < 340
  471. || myTank.getX() > 880 && myTank.getX() < 940 && myTank.getY() + 50 > 660 && myTank.getY() + 50 < 790
  472. || myTank.getX() > 260 && myTank.getX() < 320 && myTank.getY() + 50 > 660 && myTank.getY() + 50 < 790){
  473. return true;
  474. }
  475. break;
  476. }
  477. return false;
  478. }
  479. }

3.坦克基类(Tank)

  1. package com.wak.TankGame01Version;
  2. /*坦克的基类*/
  3. public class Tank {
  4. private int x; //坦克的横坐标
  5. private int y; //坦克的纵坐标
  6. private int direct = 0; //坦克的方向
  7. private int speed = 1; //坦克的速度
  8. boolean isLive = true; //坦克的存活状态
  9. public Tank(){
  10. this.x = 100; //默认坦克的初始x坐标为100
  11. this.y = 100; //默认坦克的初始y坐标为100
  12. }
  13. public Tank(int x,int y){ //自己设置坦克的初始x,y坐标
  14. this.x = x;
  15. this.y = y;
  16. }
  17. //设置坦克的x坐标
  18. public void setX(int x){
  19. this.x = x;
  20. }
  21. //设置坦克的y坐标
  22. public void setY(int y){
  23. this.y = y;
  24. }
  25. //获得坦克的x坐标
  26. public int getX(){
  27. return x;
  28. }
  29. //获得坦克的y坐标
  30. public int getY(){
  31. return y;
  32. }
  33. //设置坦克的方向
  34. public void setDirect(int direct){
  35. this.direct = direct;
  36. }
  37. //获得坦克的方向
  38. public int getDirect(){
  39. return direct;
  40. }
  41. //设置坦克的速度
  42. public void setSpeed(int speed){
  43. this.speed = speed;
  44. }
  45. //获得坦克的速度
  46. public int getSpeed(){
  47. return speed;
  48. }
  49. //坦克的上右下左移动
  50. public void MoveUp(){
  51. y -= speed;
  52. }
  53. public void MoveRight(){
  54. x += speed;
  55. }
  56. public void MoveDown(){
  57. y += speed;
  58. }
  59. public void MoveLeft(){
  60. x -= speed;
  61. }
  62. }

4.我的坦克类(MyTank)

  1. package com.wak.TankGame01Version;
  2. import java.util.Vector;
  3. /*自己的坦克*/
  4. public class MyTank extends Tank{
  5. //创建一个坦克
  6. private MyTank myTank = null;
  7. //定义一个shot对象,表示一个射击(线程)
  8. Shot shot = null;
  9. //创建一个存储炮弹的集合
  10. Vector<Shot> shots = new Vector<>();
  11. //设置坦克的初始化坐标
  12. public MyTank(int x,int y){
  13. this.setX(x);
  14. this.setY(y);
  15. }
  16. //射击
  17. public void shotOpTank(){
  18. //设置炮弹的初始化坐标及方向
  19. if(shots.size() < 5) {
  20. switch (this.getDirect()) {
  21. case 0:
  22. shot = new Shot(this.getX() + 25, this.getY(), 0);
  23. shot.speed = 4;
  24. break;
  25. case 1:
  26. shot = new Shot(this.getX() + 60, this.getY() + 25, 1);
  27. shot.speed = 4;
  28. break;
  29. case 2:
  30. shot = new Shot(this.getX() + 25, this.getY() + 60, 2);
  31. shot.speed = 4;
  32. break;
  33. case 3:
  34. shot = new Shot(this.getX(), this.getY() + 25, 3);
  35. shot.speed = 4;
  36. break;
  37. }
  38. //将发射的炮弹弹存入集合中
  39. shots.add(shot);
  40. }
  41. //启动我们的Shot线程
  42. new Thread(shot).start();
  43. }
  44. }

5.敌方坦克类(OpTank)

  1. package com.wak.TankGame01Version;
  2. import java.util.Vector;
  3. public class OpTank extends Tank implements Runnable{
  4. private OpTank opTank = null; //创建一个敌方坦克
  5. Vector<Shot> shots = new Vector<>(); //存储多个炮弹
  6. Vector<OpTank> opTanks = new Vector<>(); //增加成员,可以得到敌人坦克的Vector集合
  7. public OpTank(int x,int y){
  8. this.setX(x);
  9. this.setY(y);
  10. }
  11. public void setOpTanks(Vector<OpTank> opTanks){
  12. this.opTanks = opTanks;
  13. }
  14. public boolean isTouchOpTank(){ //防止坦克间重叠
  15. //判断当前敌人坦克的方向
  16. switch (this.getDirect()){
  17. case 0: //上
  18. for(int j=0;j<opTanks.size();j++){
  19. //取出一个敌方坦克
  20. OpTank o = opTanks.get(j);
  21. if(o != this){ //不能跟自己比
  22. //如果敌人是向上或者向下
  23. if(o.getDirect() == 0 || o.getDirect() == 2){
  24. //当前坦克左上角的坐标
  25. if(this.getX() >= o.getX()
  26. && this.getX() <= o.getX() + 50
  27. && this.getY() <= o.getY() + 60
  28. && this.getY() >= o.getY()){
  29. return true;
  30. }
  31. //当前坦克右上角的坐标
  32. if(this.getX() + 50 >= o.getX()
  33. && this.getX() + 50<= o.getX() + 50
  34. && this.getY() <= o.getY() + 60
  35. && this.getY() >= o.getY()){
  36. return true;
  37. }
  38. }
  39. //如果敌人是向右或者向左
  40. if(o.getDirect() == 1 || o.getDirect() == 3){
  41. //当前坦克左上角的坐标
  42. if(this.getX() >= o.getX()
  43. && this.getX() <= o.getX() + 60
  44. && this.getY() >= o.getY()
  45. && this.getY() <= o.getY() + 50){
  46. return true;
  47. }
  48. //当前坦克右上角的坐标
  49. if(this.getX() + 50>= o.getX()
  50. && this.getX() + 50<= o.getX() + 60
  51. && this.getY() >= o.getY()
  52. && this.getY() <= o.getY() + 50){
  53. return true;
  54. }
  55. }
  56. }
  57. }
  58. break;
  59. case 1: //右
  60. for(int j=0;j<opTanks.size();j++){
  61. //取出一辆坦克
  62. OpTank o = opTanks.get(j);
  63. if(o != this){ //不能跟自己比
  64. //如果敌方坦克是向上或向下
  65. if(o.getDirect() == 0 || o.getDirect() == 2){
  66. //当前坦克右上角的坐标
  67. if(this.getX() + 60 >= o.getX()
  68. && this.getX() + 60 <= o.getX() + 50
  69. && this.getY() >= o.getY()
  70. && this.getY() <= o.getY() + 60){
  71. return true;
  72. }
  73. //当前坦克右下角的坐标
  74. if(this.getX() + 60 >= o.getX()
  75. && this.getX() + 60 <= o.getX() + 50
  76. && this.getY() + 50 >= o.getY()
  77. && this.getY() + 50 <= o.getY() + 60){
  78. return true;
  79. }
  80. }
  81. //如果敌方坦克是向右或向左
  82. if(o.getDirect() == 1 || o.getDirect() == 3){
  83. //当前坦克右上角的坐标
  84. if(this.getX() + 60 >= o.getX()
  85. && this.getX() + 60 <= o.getX() + 60
  86. && this.getY() >= o.getY()
  87. && this.getY() <= o.getY() + 50){
  88. return true;
  89. }
  90. //当前坦克右下角的坐标
  91. if(this.getX() + 60 >= o.getX()
  92. && this.getX() + 60 <= o.getX() + 60
  93. && this.getY() + 50 >= o.getY()
  94. && this.getY() + 50 <= o.getY() + 50){
  95. return true;
  96. }
  97. }
  98. }
  99. }
  100. break;
  101. case 2: //下
  102. for(int j=0;j<opTanks.size();j++){
  103. //取出一辆坦克
  104. OpTank o = opTanks.get(j);
  105. if(o != this){ //不能跟自己比
  106. //如果敌方坦克是向上或向下
  107. if(o.getDirect() == 0 || o.getDirect() == 2){
  108. //当前坦克左下角的坐标
  109. if(this.getX() >= o.getX()
  110. && this.getX() <= o.getX() + 60
  111. && this.getY() + 60 >= o.getY()
  112. && this.getY() + 60 <= o.getY()){
  113. return true;
  114. }
  115. //当前坦克右下角的坐标
  116. if(this.getX() + 50>= o.getX()
  117. && this.getX() + 50 <= o.getX() + 60
  118. && this.getY() + 60 >= o.getY()
  119. && this.getY() + 60 <= o.getY()){
  120. return true;
  121. }
  122. }
  123. //如果敌方坦克是向右或向左
  124. if(o.getDirect() == 1 || o.getDirect() == 3){
  125. //当前坦克左下角的坐标
  126. if(this.getX() >= o.getX()
  127. && this.getX() + 60 <= o.getX() + 60
  128. && this.getY() >= o.getY()
  129. && this.getY() + 50 <= o.getY() + 50){
  130. return true;
  131. }
  132. //当前坦克右下角的坐标
  133. if(this.getX() + 50 >= o.getX()
  134. && this.getX() + 50 <= o.getX() + 60
  135. && this.getY() + 60 >= o.getY()
  136. && this.getY() + 60 <= o.getY() + 50){
  137. return true;
  138. }
  139. }
  140. }
  141. }
  142. break;
  143. case 3: //左
  144. for(int j=0;j<opTanks.size();j++){
  145. //取出一辆坦克
  146. OpTank o = opTanks.get(j);
  147. if(o != this){ //不能跟自己比
  148. //如果敌方坦克是向上或向下
  149. if(o.getDirect() == 0 || o.getDirect() == 2){
  150. //当前坦克左上角的坐标
  151. if(this.getX() >= o.getX()
  152. && this.getX() <= o.getX() + 60
  153. && this.getY() >= o.getY()
  154. && this.getY() <= o.getY()){
  155. return true;
  156. }
  157. //当前坦克左下角的坐标
  158. if(this.getX() >= o.getX()
  159. && this.getX() <= o.getX() + 60
  160. && this.getY() + 50 >= o.getY()
  161. && this.getY() + 50 <= o.getY()){
  162. return true;
  163. }
  164. }
  165. //如果敌方坦克是向右或向左
  166. if(o.getDirect() == 1 || o.getDirect() == 3){
  167. //当前坦克左上角的坐标
  168. if(this.getX() >= o.getX()
  169. && this.getX() <= o.getX() + 60
  170. && this.getY() >= o.getY()
  171. && this.getY() <= o.getY() + 50){
  172. return true;
  173. }
  174. //当前坦克左下角的坐标
  175. if(this.getX() >= o.getX()
  176. && this.getX() <= o.getX() + 60
  177. && this.getY() + 50 >= o.getY()
  178. && this.getY() + 50 <= o.getY() + 50){
  179. return true;
  180. }
  181. }
  182. }
  183. }
  184. break;
  185. }
  186. return false;
  187. }
  188. //判断敌方坦克是否触碰到了墙壁
  189. public boolean isTouchWall(){
  190. //判断敌人当前的方向
  191. switch (getDirect()){
  192. case 0: //向上
  193. for(int i=0;i<opTanks.size();i++){ //取出一个坦克
  194. OpTank o = opTanks.get(i);
  195. //当前坦克的左上角坐标
  196. if(o.getX() > 500 && o.getX() < 700 && o.getY() > 660 && o.getY() < 710
  197. // || o.getX() > 160 && o.getX() <= 290 && o.getY() > 100 && o.getY() <= 160
  198. // || o.getX() > 910 && o.getX() <= 1040 && o.getY() > 100 && o.getY() <= 160
  199. || o.getX() > 550 && o.getX() < 650 && o.getY() > 160 && o.getY() < 260
  200. || o.getX() > 790 && o.getX() < 850 && o.getY() > 100 && o.getY() < 160
  201. || o.getX() > 350 && o.getX() < 410 && o.getY() > 100 && o.getY() < 340
  202. || o.getX() > 880 && o.getX() < 940 && o.getY() > 660 && o.getY() < 790
  203. || o.getX() > 260 && o.getX() < 320 && o.getY() > 660 && o.getY() < 790){
  204. return true;
  205. }
  206. //当前坦克的右上角坐标
  207. if(o.getX() + 50 > 500 && o.getX() + 50 < 700 && o.getY() > 660 && o.getY() < 710
  208. // || o.getX() + 50 >= 160 && o.getX() + 50 <= 290 && o.getY() >= 100 && o.getY() <= 160
  209. // || o.getX() + 50 >= 910 && o.getX() + 50 <= 1040 && o.getY() >= 100 && o.getY() <= 160
  210. || o.getX() + 50 > 550 && o.getX() + 50 < 650 && o.getY() > 160 && o.getY() < 260
  211. || o.getX() + 50 > 790 && o.getX() + 50 < 850 && o.getY() > 100 && o.getY() < 160
  212. || o.getX() + 50 > 350 && o.getX() + 50 < 410 && o.getY() > 100 && o.getY() < 340
  213. || o.getX() + 50 > 880 && o.getX() + 50 < 940 && o.getY() > 660 && o.getY() < 790
  214. || o.getX() + 50 > 260 && o.getX() + 50 < 320 && o.getY() > 660 && o.getY() < 790){
  215. return true;
  216. }
  217. }
  218. break;
  219. case 1: //向右
  220. for(int i=0;i<opTanks.size();i++) { //取出一个坦克
  221. OpTank o = opTanks.get(i);
  222. //当前坦克的右上角坐标
  223. if (o.getX() + 60 > 500 && o.getX() + 60 < 700 && o.getY() > 660 && o.getY() < 710
  224. // || o.getX() + 60 >= 160 && o.getX() + 60 <= 290 && o.getY() >= 100 && o.getY() <= 160
  225. // || o.getX() + 60 >= 910 && o.getX() + 60 <= 1040 && o.getY() >= 100 && o.getY() <= 160
  226. || o.getX() + 60 > 550 && o.getX() + 60 < 650 && o.getY() > 160 && o.getY() < 260
  227. || o.getX() + 60 > 790 && o.getX() + 60 < 850 && o.getY() > 100 && o.getY() < 160
  228. || o.getX() + 60 > 350 && o.getX() + 60 < 410 && o.getY() > 100 && o.getY() < 340
  229. || o.getX() + 60 > 880 && o.getX() + 60 < 940 && o.getY() > 660 && o.getY() < 790
  230. || o.getX() + 60 > 260 && o.getX() + 60 < 320 && o.getY() > 660 && o.getY() < 790){
  231. return true;
  232. }
  233. //当前坦克的右下角坐标
  234. if(o.getX() + 60 > 500 && o.getX() + 60 < 700 && o.getY() + 50 > 660 && o.getY() + 50 < 710
  235. // || o.getX() + 60 >= 160 && o.getX() + 60 <= 290 && o.getY() + 50 >= 100 && o.getY() + 50 <= 160
  236. // || o.getX() + 60 >= 910 && o.getX() + 60 <= 1040 && o.getY() + 50 >= 100 && o.getY() + 50 <= 160
  237. || o.getX() + 60 > 550 && o.getX() + 60 < 650 && o.getY() + 50 > 160 && o.getY() + 50 < 260
  238. || o.getX() + 60 > 790 && o.getX() + 60 < 850 && o.getY() + 50 > 100 && o.getY() + 50 < 160
  239. || o.getX() + 60 > 350 && o.getX() + 60 < 410 && o.getY() + 50 > 100 && o.getY() + 50 < 340
  240. || o.getX() + 60 > 880 && o.getX() + 60 < 940 && o.getY() + 50 > 660 && o.getY() + 50 < 790
  241. || o.getX() + 60 > 260 && o.getX() + 60 < 320 && o.getY() + 50 > 660 && o.getY() + 50 < 790){
  242. return true;
  243. }
  244. }
  245. break;
  246. case 2: //向下
  247. for(int i=0;i<opTanks.size();i++) { //取出一个坦克
  248. OpTank o = opTanks.get(i);
  249. //当前坦克的左下角坐标
  250. if(o.getX() > 500 && o.getX() < 700 && o.getY() + 60 > 660 && o.getY() + 60 < 710
  251. // || o.getX() >= 160 && o.getX() <= 290 && o.getY() + 60 >= 100 && o.getY() + 60 <= 160
  252. // || o.getX() >= 910 && o.getX() <= 1040 && o.getY() + 60 >= 100 && o.getY() + 60 <= 160
  253. || o.getX() > 550 && o.getX() < 650 && o.getY() + 60 > 160 && o.getY() + 60 < 260
  254. || o.getX() > 790 && o.getX() < 850 && o.getY() + 60 > 100 && o.getY() + 60 < 160
  255. || o.getX() > 350 && o.getX() < 410 && o.getY() + 60 > 100 && o.getY() + 60 < 340
  256. || o.getX() > 880 && o.getX() < 940 && o.getY() + 60 > 660 && o.getY() + 60 < 790
  257. || o.getX() > 260 && o.getX() < 320 && o.getY() + 60 > 660 && o.getY() + 60 < 790){
  258. return true;
  259. }
  260. //当前坦克的右下角坐标
  261. if(o.getX() + 50 > 500 && o.getX() + 50 < 700 && o.getY() + 60 > 660 && o.getY() + 60 < 710
  262. // || o.getX() + 50 >= 160 && o.getX() + 50 <= 290 && o.getY() + 60 >= 100 && o.getY() + 60 <= 160
  263. // || o.getX() + 50 >= 910 && o.getX() + 50 <= 1040 && o.getY() + 60 >= 100 && o.getY() + 60 <= 160
  264. || o.getX() + 50 > 550 && o.getX() + 50 < 650 && o.getY() + 60 > 160 && o.getY() + 60 < 260
  265. || o.getX() + 50 > 790 && o.getX() + 50 < 850 && o.getY() + 60 > 100 && o.getY() + 60 < 160
  266. || o.getX() + 50 > 350 && o.getX() + 50 < 410 && o.getY() + 60 > 100 && o.getY() + 60 < 340
  267. || o.getX() + 50 > 880 && o.getX() + 50 < 940 && o.getY() + 60 > 660 && o.getY() + 60 < 790
  268. || o.getX() + 50 > 260 && o.getX() + 50 < 320 && o.getY() + 60 > 660 && o.getY() + 60 < 790){
  269. return true;
  270. }
  271. }
  272. break;
  273. case 3: //向左
  274. for(int i=0;i<opTanks.size();i++) { //取出一个坦克
  275. OpTank o = opTanks.get(i);
  276. //当前坦克的左上角坐标
  277. if(o.getX() > 500 && o.getX() < 700 && o.getY() > 660 && o.getY() < 710
  278. // || o.getX() >= 160 && o.getX() <= 290 && o.getY() >= 100 && o.getY() <= 160
  279. // || o.getX() >= 910 && o.getX() <= 1040 && o.getY() >= 100 && o.getY() <= 160
  280. || o.getX() > 550 && o.getX() < 650 && o.getY() > 160 && o.getY() < 260
  281. || o.getX() > 790 && o.getX() < 850 && o.getY() > 100 && o.getY() < 160
  282. || o.getX() > 350 && o.getX() < 410 && o.getY() > 100 && o.getY() < 340
  283. || o.getX() > 880 && o.getX() < 940 && o.getY() > 660 && o.getY() < 790
  284. || o.getX() > 260 && o.getX() < 320 && o.getY() > 660 && o.getY() < 790){
  285. return true;
  286. }
  287. //当前坦克的左下角坐标
  288. if(o.getX() > 500 && o.getX() < 700 && o.getY() + 50 > 660 && o.getY() + 50 < 710
  289. || o.getX() > 160 && o.getX() < 290 && o.getY() + 50 > 100 && o.getY() + 50 < 160
  290. || o.getX() > 910 && o.getX() < 1040 && o.getY() + 50 > 100 && o.getY() + 50 < 160
  291. || o.getX() > 550 && o.getX() < 650 && o.getY() + 50 > 160 && o.getY() + 50 < 260
  292. || o.getX() > 790 && o.getX() < 850 && o.getY() + 50 > 100 && o.getY() + 50 < 160
  293. || o.getX() > 350 && o.getX() < 410 && o.getY() + 50 > 100 && o.getY() + 50 < 340
  294. || o.getX() > 880 && o.getX() < 940 && o.getY() + 50 > 660 && o.getY() + 50 < 790
  295. || o.getX() > 260 && o.getX() < 320 && o.getY() + 50 > 660 && o.getY() + 50 < 790){
  296. return true;
  297. }
  298. }
  299. break;
  300. }
  301. return false;
  302. }
  303. @Override
  304. public void run() {
  305. while(true){
  306. //这里判断坦克的方向,创建对应的炮弹
  307. if(isLive && shots.size() < 6){
  308. Shot s = null;
  309. switch (getDirect()){
  310. case 0:
  311. s = new Shot(getX() + 25,getY(),0);
  312. break;
  313. case 1:
  314. s = new Shot(getX() + 60,getY() + 25,1);
  315. break;
  316. case 2:
  317. s = new Shot(getX() + 25,getY() + 60,2);
  318. break;
  319. case 3:
  320. s = new Shot(getX(),getY() + 25,3);
  321. break;
  322. }
  323. //每隔2秒发射一个炮弹
  324. try {
  325. Thread.sleep(2000);
  326. } catch (InterruptedException e) {
  327. e.printStackTrace();
  328. }
  329. shots.add(s);
  330. new Thread(s).start();
  331. }
  332. //坦克移动的方向
  333. switch (this.getDirect()){
  334. case 0:
  335. for(int i=0;i<60;i++) {
  336. if (getY() > 0 && !isTouchOpTank() && !isTouchWall()){
  337. MoveUp();
  338. }
  339. //休眠
  340. try {
  341. Thread.sleep(50);
  342. } catch (InterruptedException e) {
  343. e.printStackTrace();
  344. }
  345. }
  346. break;
  347. case 1:
  348. for (int i=0;i<60;i++){
  349. if(getX() + 60< 1200 && !isTouchOpTank() && !isTouchWall()) {
  350. MoveRight();
  351. }
  352. //休眠
  353. try {
  354. Thread.sleep(50);
  355. } catch (InterruptedException e) {
  356. e.printStackTrace();
  357. }
  358. }
  359. break;
  360. case 2:
  361. for (int i=0;i<60;i++){
  362. if(getY() + 60 < 900 && !isTouchOpTank() && !isTouchWall()) {
  363. MoveDown();
  364. }
  365. //休眠
  366. try {
  367. Thread.sleep(50);
  368. } catch (InterruptedException e) {
  369. e.printStackTrace();
  370. }
  371. }
  372. break;
  373. case 3:
  374. for (int i=0;i<60;i++){
  375. if(getX() > 0 && !isTouchOpTank() && !isTouchWall()) {
  376. MoveLeft();
  377. }
  378. //休眠
  379. try {
  380. Thread.sleep(50);
  381. } catch (InterruptedException e) {
  382. e.printStackTrace();
  383. }
  384. }
  385. break;
  386. }
  387. setDirect((int)(Math.random() * 4));
  388. // System.out.println("坦克的x坐标" + getX() + " y坐标 "+ getY() );
  389. if(!isLive){
  390. break;
  391. }
  392. }
  393. }
  394. }

6.炮弹类(Shot)

  1. package com.wak.TankGame01Version;
  2. public class Shot implements Runnable{
  3. int x; //子弹的x坐标
  4. int y; //子弹的y坐标
  5. int direct = 0; //子弹的方向
  6. int speed = 4; //子弹的速度
  7. boolean isLive = true; //子弹的存活状态
  8. public Shot(int x,int y,int direct){
  9. this.x = x;
  10. this.y = y;
  11. this.direct = direct;
  12. }
  13. public void setShotSpeed(int speed){
  14. this.speed = speed;
  15. }
  16. @Override
  17. public void run() { //射击
  18. while(isLive){
  19. //休眠
  20. try {
  21. Thread.sleep(50);
  22. } catch (InterruptedException e) {
  23. e.printStackTrace();
  24. }
  25. switch (direct){
  26. case 0: //向上
  27. y -= speed;
  28. break;
  29. case 1: //向右
  30. x += speed;
  31. break;
  32. case 2: //向下
  33. y += speed;
  34. break;
  35. case 3: //向左
  36. x -= speed;
  37. break;
  38. }
  39. // System.out.println("炮弹的x坐标:" + x + ",炮弹的y坐标:" + y);
  40. //如果炮弹弹撞到墙壁,则销毁
  41. //当炮弹碰到敌人坦克时,也应当结束
  42. if(!(x > 0 && x < 1200 && y > 0 && y <= 900 && isLive)
  43. // || x >= 160 && x <= 290 && y >= 100 && y <= 160
  44. // || x >= 910 && x<= 1040 && y >= 100 && y <= 160
  45. || x > 550 && x < 650 && y > 160 && y < 260
  46. || x > 790 && x < 850 && y > 100 && y < 340
  47. || x > 350 && x < 410 && y > 100 && y < 340
  48. || x > 880 && x < 940 && y > 660 && y < 790
  49. || x > 260 && x < 320 && y > 660 && y < 790
  50. || x > 500 && x < 700 && y > 660 && y < 710){
  51. isLive = false;
  52. // System.out.println("炮弹已销毁");
  53. }
  54. }
  55. }
  56. }

7.记录信息类(Recorder)

  1. package com.wak.TankGame01Version;
  2. import java.awt.*;
  3. import java.io.*;
  4. import java.util.Vector;
  5. public class Recorder {
  6. private static int allOpTanksNum = 0;
  7. //定义IO对象,准备写数据到文件中
  8. private static FileWriter fw = null;
  9. private static BufferedWriter bw = null;
  10. private static BufferedReader br = null;
  11. private static String recordFile = "D:\\myTankGameRecord.txt";
  12. //定义Vec,指向GamePanel对象的 敌人坦克Vector
  13. private static Vector<OpTank> opTanks = null;
  14. //定义一个Node 的Vector,用于保存敌人的信息node
  15. private static Vector<Node> nodes = new Vector<>();
  16. public static void setOpTanks(Vector<OpTank> opTanks){
  17. Recorder.opTanks = opTanks;
  18. }
  19. public static int getAllOpTanksNum(){
  20. return allOpTanksNum;
  21. }
  22. public static void setAllOpTanksNum(int allOpTanksNum){
  23. Recorder.allOpTanksNum = allOpTanksNum;
  24. }
  25. //当我方坦克击毁一个敌人坦克,就应当allOpTanksNum++
  26. public static void addAllOpTanksNum(){
  27. Recorder.allOpTanksNum++;
  28. }
  29. //增加一个方法,当游戏退出时,我们将allOpTanksNum保存到recordFile
  30. //对KeepRecord方法进行升级,保存敌人坦克的坐标和方向
  31. public static void KeepRecord(){
  32. try {
  33. bw = new BufferedWriter((new FileWriter((recordFile))));
  34. bw.write(allOpTanksNum + "\r\n");
  35. //遍历敌人坦克的Vector,然后根据情况保存即可
  36. for(int i=0;i<opTanks.size();i++){
  37. //取出敌人坦克
  38. OpTank o = opTanks.get(i);
  39. if(o.isLive){
  40. //保存该opTank的信息
  41. String record = o.getX() + " " + o.getY() + " " + o.getDirect();
  42. //写入到文件
  43. bw.write(record + "\r\n");
  44. }
  45. }
  46. } catch (IOException e) {
  47. e.printStackTrace();
  48. }finally {
  49. if (bw != null) {
  50. try {
  51. bw.close();
  52. } catch (IOException e) {
  53. e.printStackTrace();
  54. }
  55. }
  56. }
  57. }
  58. // //增加一个方法,用于读取recordFile,恢复相关信息
  59. // public static Vector<Node> getNodesAndEnemyTankRec(){
  60. // try {
  61. // br = new BufferedReader(new FileReader(recordFile));
  62. //
  63. // } catch (FileNotFoundException e) {
  64. // e.printStackTrace();
  65. // }finally {
  66. //
  67. // }
  68. // return null;
  69. // }
  70. }

运行效果截图:

 

 

总结:

这次短学期实践,给我带来了很大收获,让我的时间变得充实,让我收获了写电子笔记,写总结的好习惯,让我能像被封印在椅子上一样,就这么写代码写一整个下午,也深刻的意识到写一个项目或者是一段代码,一定要先有自己的思路,思路是最重要的,是基础,才能去实现,也很感谢老师们,和学长学姐们,以及各位与我一起参加短学期实践的小伙伴们,是他们让我认识到了自己的不足,是他们让我学会了很多对于学习中很有用的方法,见证到了代码的魅力,让我们一起继续加油,尽最大的努力,做最好的自己,为了我爱的和爱我的!

声明:本文内容由网友自发贡献,不代表【wpsshop博客】立场,版权归原作者所有,本站不承担相应法律责任。如您发现有侵权的内容,请联系我们。转载请注明出处:https://www.wpsshop.cn/w/AllinToyou/article/detail/326339
推荐阅读
相关标签
  

闽ICP备14008679号