赞
踩
/*首先要声明的是,这个并不是坦克大战项目编写细节的过程分享,只是个人的阶段学习记录及总结,坦克大战的项目可以参考B站上韩顺平老师的视频教学*/
小总结:今天刚开始,跟着视频一起学习编写坦克大战的项目,首先,我觉得对于编写一个项目,最重要的就是要构思好一个框架,比如,你写一个项目,要设几个类,每个类分别有什么作用。但是也不要太过于想提前想好要写什么方法(函数),我们只需要先构思好大的类,具体的,等到我们自己去写的时候,是可以慢慢再实现的。最重要的,一定是首先要有一个明确的思路。比如这个坦克大战的编写,目前写了五个类:主程序类,游戏界面绘制类,坦克基类,我的坦克类,敌方坦克类。思路是:先进行游戏界面的绘制,再画出坦克的图形,此时是静态的。然后再到动态的坦克编写,今天最后完成的,就是敌方坦克的绘制,因为敌方坦克会有许多特有的方法,所以要单独成一个类。因此,我对面向对象设计,或者说是对程序设计的感受是,最重要的就是有一个明确的思路,有一个框架,里面的内容是可以慢慢去填充的。
今天“手痒”测试了一下,给敌方一个坦克添加了键盘监听事件,让我觉得写成之后,甚至可以写一个双人1V1的坦克大战,但是我在移动的时候,我发现,一次只能移动一辆坦克,要想同时移动两辆坦克,目前肯定是不行的。下一个阶段是学习多线程,因此我想到了实现多线程,应该就是为了多个坦克可以同时移动。
以下是今天的代码记录截图:
五个类(根据英文应该能猜到各自对应什么)
1.主程序类(TankGame01)
- package com.wak.TankGame01Version;
-
- import javax.swing.*;
-
- /*坦克大战游戏主程序*/
- public class TankGame01 extends JFrame {
- public static void main(String[] args) {
- //启动!
- new TankGame01();
- }
-
- //定义GamePanel,创建游戏环境
- GamePanel gamePanel = null;
-
- //加载游戏环境
- public TankGame01(){
- //1.0版本
- this.setTitle("坦克大战1.0");
- //加载游戏环境
- gamePanel = new GamePanel();
- //将游戏区域加载到界面里
- this.add(gamePanel);
- //将键盘监听器加载到界面里
- this.addKeyListener(gamePanel);
- //设置界面可视化
- this.setVisible(true);
- //设置界面的大小
- this.setSize(1000,800);
- //设置界面可关闭
- this.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
- }
-
- }

2.游戏界面绘制类(GamePanel)
- package com.wak.TankGame01Version;
-
- import javax.swing.*;
- import java.awt.*;
- import java.awt.event.KeyEvent;
- import java.awt.event.KeyListener;
- import java.util.Vector;
-
- /*坦克大战的绘图区域*/
- public class GamePanel extends JPanel implements KeyListener {
- //定义一个自己的坦克
- MyTank myTank = null;
-
- //创建敌方坦克
- Vector<OpTank> opTanks = new Vector<>();
- //设置敌方坦克数量
- int opTanksSize = 3;
-
- public GamePanel(){
- myTank = new MyTank(200,600); //初始化坦克的位置
- myTank.setSpeed(3); //设置坦克的速度
-
- for(int i=0;i<opTanksSize;i++){
- OpTank opTank = new OpTank((100 * i + 100),0);
- opTank.setDirect(2);
- opTanks.add(opTank);
- }
- }
-
-
- @Override
- public void paint(Graphics g) {
- super.paint(g);
- g.fillRect(0,0,1000,800); //默认背景是黑色
-
- //画出坦克-封装方法
- DrawTank(myTank.getX(),myTank.getY(),g,myTank.getDirect(),0);
- DrawTank(myTank.getX(),myTank.getY(),g,myTank.getDirect(),0);
- for(int i=0;i<opTanks.size();i++){
- //取出敌方坦克
- OpTank opTank = opTanks.get(i);
- DrawTank(opTank.getX(),opTank.getY(),g,opTank.getDirect(),1);
- }
- }
-
- //编写方法,画出坦克
-
- /**
- *
- * @param x 坦克的x坐标
- * @param y 坦克的y坐标
- * @param g 画笔
- * @param direct 坦克方向(上下左右)
- * @param type 坦克类型
- */
- public void DrawTank(int x,int y,Graphics g,int direct,int type){
- //坦克的类型
- switch (type){
- case 0: //自己的坦克
- g.setColor(Color.CYAN);
- break;
- case 1: //敌人的坦克
- g.setColor(Color.RED);
- break;
- }
-
- switch (direct){
- case 0: //表示向上
- g.fill3DRect(x,y,10,60,false); //坦克的左边轮子
- g.drawLine(x,y + 10,x + 10,y + 10); //坦克左轮的履带
- g.drawLine(x,y + 20,x + 10,y + 20);
- g.drawLine(x,y + 30,x + 10,y + 30);
- g.drawLine(x,y + 40,x + 10,y + 40);
- g.drawLine(x,y + 50,x + 10,y + 50);
-
- g.fill3DRect(x + 40,y,10,60,false); //坦克的右边轮子
- g.drawLine(x + 40,y + 10,x + 50,y + 10); //坦克右轮的履带
- g.drawLine(x + 40,y + 20,x + 50,y + 20);
- g.drawLine(x + 40,y + 30,x + 50,y + 30);
- g.drawLine(x + 40,y + 40,x + 50,y + 40);
- g.drawLine(x + 40,y + 50,x + 50,y + 50);
-
- g.fill3DRect(x + 10,y + 10,30,40,false); //坦克的身体
- g.fillOval(x + 10,y + 15,30,30); //坦克的炮盖
- g.drawLine(x + 25,y + 30,x + 25,y); //坦克的炮筒
- break;
-
- case 1: //表示向右
- g.fill3DRect(x,y,60,10,false); //坦克左边的轮子
- g.drawLine(x + 10,y,x + 10 ,y + 10); //坦克左轮的履带
- g.drawLine(x + 20,y,x + 20 ,y + 10);
- g.drawLine(x + 30,y,x + 30 ,y + 10);
- g.drawLine(x + 40,y,x + 40 ,y + 10);
- g.drawLine(x + 50,y,x + 50 ,y + 10);
-
-
- g.fill3DRect(x,y + 40,60,10,false); //坦克右边的轮子
- g.drawLine(x + 10,y + 40,x + 10,y + 50);
- g.drawLine(x + 20,y + 40,x + 20,y + 50);
- g.drawLine(x + 30,y + 40,x + 30,y + 50);
- g.drawLine(x + 40,y + 40,x + 40,y + 50);
- g.drawLine(x + 50,y + 40,x + 50,y + 50);
-
-
- g.fill3DRect( x + 10,y + 10,40,30,false); //坦克的身体
- g.fillOval(x + 15,y + 10,30,30); //坦克的炮盖
- g.drawLine(x + 30,y + 25,x +60,y + 25); //坦克的炮筒
- break;
-
- case 2: //表示向下
- g.fill3DRect(x,y,10,60,false); //坦克的左边轮子
- g.drawLine(x,y + 10,x + 10,y + 10); //坦克左轮的履带
- g.drawLine(x,y + 20,x + 10,y + 20);
- g.drawLine(x,y + 30,x + 10,y + 30);
- g.drawLine(x,y + 40,x + 10,y + 40);
- g.drawLine(x,y + 50,x + 10,y + 50);
-
- g.fill3DRect(x + 40,y,10,60,false); //坦克的右边轮子
- g.drawLine(x + 40,y + 10,x + 50,y + 10); //坦克右轮的履带
- g.drawLine(x + 40,y + 20,x + 50,y + 20);
- g.drawLine(x + 40,y + 30,x + 50,y + 30);
- g.drawLine(x + 40,y + 40,x + 50,y + 40);
- g.drawLine(x + 40,y + 50,x + 50,y + 50);
-
- g.fill3DRect(x + 10,y + 10,30,40,false); //坦克的身体
- g.fillOval(x + 10,y + 15,30,30); //坦克的炮盖
- g.drawLine(x + 25,y + 30,x + 25,y + 60); //坦克的炮筒
- break;
-
- case 3: //表示向左
- g.fill3DRect(x,y,60,10,false); //坦克左边的轮子
- g.drawLine(x + 10,y,x + 10 ,y + 10); //坦克左轮的履带
- g.drawLine(x + 20,y,x + 20 ,y + 10);
- g.drawLine(x + 30,y,x + 30 ,y + 10);
- g.drawLine(x + 40,y,x + 40 ,y + 10);
- g.drawLine(x + 50,y,x + 50 ,y + 10);
-
-
- g.fill3DRect(x,y + 40,60,10,false); //坦克右边的轮子
- g.drawLine(x + 10,y + 40,x + 10,y + 50);
- g.drawLine(x + 20,y + 40,x + 20,y + 50);
- g.drawLine(x + 30,y + 40,x + 30,y + 50);
- g.drawLine(x + 40,y + 40,x + 40,y + 50);
- g.drawLine(x + 50,y + 40,x + 50,y + 50);
-
-
- g.fill3DRect( x + 10,y + 10,40,30,false); //坦克的身体
- g.fillOval(x + 15,y + 10,30,30); //坦克的炮盖
- g.drawLine(x + 30,y + 25,x,y + 25); //坦克的炮筒
- break;
-
- default:
- System.out.println("暂时没有处理");
- }
- }
-
- @Override
- public void keyTyped(KeyEvent e) {
-
- }
-
- @Override
- public void keyPressed(KeyEvent e) {
- if(e.getKeyCode() == KeyEvent.VK_W){
- myTank.setDirect(0);
- myTank.MoveUp();
- }else if(e.getKeyCode() == KeyEvent.VK_D){
- myTank.setDirect(1);
- myTank.MoveRight();
- }else if(e.getKeyCode() == KeyEvent.VK_S){
- myTank.setDirect(2);
- myTank.MoveDown();
- }else if(e.getKeyCode() == KeyEvent.VK_A){
- myTank.setDirect(3);
- myTank.MoveLeft();
- }
- // else if(e.getKeyCode() == KeyEvent.VK_UP){
- // opTanks.get(0).setDirect(0);
- // opTanks.get(0).MoveUp();
- // }else if(e.getKeyCode() == KeyEvent.VK_RIGHT){
- // opTanks.get(0).setDirect(1);
- // opTanks.get(0).MoveRight();
- // }else if(e.getKeyCode() == KeyEvent.VK_DOWN){
- // opTanks.get(0).setDirect(2);
- // opTanks.get(0).MoveDown();
- // }else if(e.getKeyCode() == KeyEvent.VK_LEFT) {
- // opTanks.get(0).setDirect(3);
- // opTanks.get(0).MoveLeft();
- // }
- this.repaint();
-
- }
-
- @Override
- public void keyReleased(KeyEvent e) {
-
- }
- }

3.坦克基类(Tank)
- package com.wak.TankGame01Version;
-
- /*坦克的基类*/
- public class Tank {
- private int x; //坦克的横坐标
- private int y; //坦克的纵坐标
- private int direct = 0; //坦克的方向
- private int speed = 1; //坦克的速度
-
- public Tank(){
- this.x = 100; //默认坦克的初始x坐标为100
- this.y = 100; //默认坦克的初始y坐标为100
- }
-
- public Tank(int x,int y){ //自己设置坦克的初始x,y坐标
- this.x = x;
- this.y = y;
- }
-
-
- //设置坦克的x坐标
- public void setX(int x){
- this.x = x;
- }
-
- //设置坦克的y坐标
- public void setY(int y){
- this.y = y;
- }
-
- //获得坦克的x坐标
- public int getX(){
- return x;
- }
-
- //获得坦克的y坐标
- public int getY(){
- return y;
- }
-
- //设置坦克的方向
- public void setDirect(int direct){
- this.direct = direct;
- }
-
- //获得坦克的方向
- public int getDirect(){
- return direct;
- }
-
- //设置坦克的速度
- public void setSpeed(int speed){
- this.speed = speed;
- }
-
- //获得坦克的速度
- public int getSpeed(){
- return speed;
- }
-
- //坦克的上右下左移动
- public void MoveUp(){
- y -= speed;
- }
- public void MoveRight(){
- x += speed;
- }
- public void MoveDown(){
- y += speed;
- }
- public void MoveLeft(){
- x -= speed;
- }
- }
-
-

4.我的坦克类(MyTank)
- package com.wak.TankGame01Version;
-
- /*自己的坦克*/
- public class MyTank extends Tank{
- //创建一个坦克
- private MyTank myTank = null;
- //设置坦克的初始化坐标
- public MyTank(int x,int y){
- this.setX(x);
- this.setY(y);
- }
-
-
- }
5.敌方坦克类(OpTank)
- package com.wak.TankGame01Version;
-
- public class OpTank extends Tank{
- private OpTank opTank = null;
-
- public OpTank(int x,int y){
- this.setX(x);
- this.setY(y);
- }
-
-
- }
运行效果:(蓝色是我的坦克,红色是敌方坦克,蓝色坦克可以上下左右移动)
小总结:今天接续昨天的内容,完成了我的坦克的发射炮弹,敌方坦克发射子弹,敌方坦克消失,敌方坦克自由移动,以及控制坦克移动的范围。我发现到这里,才真正写到了坦克大战的比较核心的、难的部分,那就是多线程。先简要的说一下今天学习的编写思路吧:因为炮弹是我的和敌方坦克都有的,所以需要单独写一个类,所以今天加了一个Shot类,但是因为你要射击的时候,它也要在界面上移动,所以这时候就需要用到多线程,像敌方坦克发射炮弹,敌方坦克移动,都是要用到多线程,而其中的另一个关键就是,在哪里启动,而这其中有很多思路是很巧妙的,比如,对于控制坦克的移动范围,我以为要另外写一个方法去进行判断的时候,韩老师的思路就是直接在控制坦克上下左右移动的代码上进行一个if判断,这样直接且非常巧妙的解决了问题,再比如,绘制敌方坦克的时候,先判断一下敌方坦克是否存活,再进行绘制,这样又提高了代码的运行效率,等等等。我发现,对于写一个程序,甚至是一段代码,一定要先想一想,构思一下,确立好思路再动手,尽量发散一下思维。
以下是今天的代码记录截图:
六个类(根据英文应该能猜到各自对应什么)
1.主程序类(TankGame01)
- package com.wak.TankGame01Version;
-
- import javax.swing.*;
-
- /*坦克大战游戏主程序*/
- public class TankGame01 extends JFrame {
- public static void main(String[] args) {
- //启动!
- new TankGame01();
- }
-
- //定义GamePanel,创建游戏环境
- GamePanel gamePanel = null;
-
- //加载游戏环境
- public TankGame01(){
- //1.0版本
- this.setTitle("坦克大战1.0");
- //加载游戏环境
- gamePanel = new GamePanel();
- //将游戏区域加载到界面里
- this.add(gamePanel);
- //将游戏界面的炮弹线程加入到界面里
- Thread thread = new Thread(gamePanel);
- //启动子线程
- thread.start();
- //将键盘监听器加载到界面里
- this.addKeyListener(gamePanel);
- //设置界面可视化
- this.setVisible(true);
- //设置界面的大小
- this.setSize(1000,800);
- //设置界面可关闭
- this.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
- }
-
- }

2.游戏界面绘制类(GamePanel)
- package com.wak.TankGame01Version;
-
- import javax.swing.*;
- import java.awt.*;
- import java.awt.event.KeyEvent;
- import java.awt.event.KeyListener;
- import java.util.Vector;
-
- /*坦克大战的绘图区域*/
-
- //为了监听键盘事件,实现KeyListener
- //
- public class GamePanel extends JPanel implements KeyListener,Runnable{
- //定义一个自己的坦克
- MyTank myTank = null;
-
- //创建敌方坦克
- Vector<OpTank> opTanks = new Vector<>();
- //设置敌方坦克数量
- int opTanksSize = 3;
-
- public GamePanel(){
- myTank = new MyTank(200,600); //初始化坦克的位置
- myTank.setSpeed(3); //设置坦克的速度
-
- for(int i=0;i<opTanksSize;i++){
- OpTank opTank = new OpTank((100 * i + 100),0);
- //设置方向
- opTank.setDirect(2);
- //启动敌人坦克线程
- new Thread(opTank).start();
- //给该opTank加入一颗炮弹
- Shot shot = new Shot(opTank.getX() + 25,opTank.getY() + 60,2);
- //存放到Vector中
- opTank.shots.add(shot);
- //启动线程对象
- new Thread(shot).start();
- //加入
- opTanks.add(opTank);
- }
- }
-
-
- @Override
- public void paint(Graphics g) {
- super.paint(g);
- g.fillRect(0,0,1000,800); //默认背景是黑色
-
- //画出坦克-封装方法
- //画出我的坦克
- DrawTank(myTank.getX(),myTank.getY(),g,myTank.getDirect(),0);
- //画出敌人的坦克
- for(int i=0;i<opTanks.size();i++){
- //取出敌方坦克
- OpTank opTank = opTanks.get(i);
- //判断敌方坦克是否存活
- if(opTank.isLive) { //当敌人坦克是存活的时候,才去画
- DrawTank(opTank.getX(), opTank.getY(), g, opTank.getDirect(), 1);
- //画出敌人的坦克发出的炮弹
- for (int j = 0; j < opTank.shots.size(); j++) {
- //取出子弹
- Shot shot = opTank.shots.get(j);
- //绘制
- if (shot.isLive) {
- g.setColor(Color.WHITE);
- g.fill3DRect(shot.x, shot.y, 4, 4, false);
- } else {
- opTank.shots.remove(shot);
- }
- }
- }
-
- }
-
- //画出我的坦克发出的炮弹
- if(myTank.shot != null && myTank.shot.isLive == true){
- g.setColor(Color.CYAN);
- g.fill3DRect(myTank.shot.x,myTank.shot.y,4,4,false);
- }
-
-
-
- }
-
- //编写方法,画出坦克
-
- /**
- *
- * @param x 坦克的x坐标
- * @param y 坦克的y坐标
- * @param g 画笔
- * @param direct 坦克方向(上下左右)
- * @param type 坦克类型
- */
- public void DrawTank(int x,int y,Graphics g,int direct,int type){
- //坦克的类型
- switch (type){
- case 0: //自己的坦克
- g.setColor(Color.CYAN);
- break;
- case 1: //敌人的坦克
- g.setColor(Color.RED);
- break;
- }
-
- switch (direct){
- case 0: //表示向上
- g.fill3DRect(x,y,10,60,false); //坦克的左边轮子
- g.drawLine(x,y + 10,x + 10,y + 10); //坦克左轮的履带
- g.drawLine(x,y + 20,x + 10,y + 20);
- g.drawLine(x,y + 30,x + 10,y + 30);
- g.drawLine(x,y + 40,x + 10,y + 40);
- g.drawLine(x,y + 50,x + 10,y + 50);
-
- g.fill3DRect(x + 40,y,10,60,false); //坦克的右边轮子
- g.drawLine(x + 40,y + 10,x + 50,y + 10); //坦克右轮的履带
- g.drawLine(x + 40,y + 20,x + 50,y + 20);
- g.drawLine(x + 40,y + 30,x + 50,y + 30);
- g.drawLine(x + 40,y + 40,x + 50,y + 40);
- g.drawLine(x + 40,y + 50,x + 50,y + 50);
-
- g.fill3DRect(x + 10,y + 10,30,40,false); //坦克的身体
- g.fillOval(x + 10,y + 15,30,30); //坦克的炮盖
- g.drawLine(x + 25,y + 30,x + 25,y); //坦克的炮筒
- break;
-
- case 1: //表示向右
- g.fill3DRect(x,y,60,10,false); //坦克左边的轮子
- g.drawLine(x + 10,y,x + 10 ,y + 10); //坦克左轮的履带
- g.drawLine(x + 20,y,x + 20 ,y + 10);
- g.drawLine(x + 30,y,x + 30 ,y + 10);
- g.drawLine(x + 40,y,x + 40 ,y + 10);
- g.drawLine(x + 50,y,x + 50 ,y + 10);
-
-
- g.fill3DRect(x,y + 40,60,10,false); //坦克右边的轮子
- g.drawLine(x + 10,y + 40,x + 10,y + 50);
- g.drawLine(x + 20,y + 40,x + 20,y + 50);
- g.drawLine(x + 30,y + 40,x + 30,y + 50);
- g.drawLine(x + 40,y + 40,x + 40,y + 50);
- g.drawLine(x + 50,y + 40,x + 50,y + 50);
-
-
- g.fill3DRect( x + 10,y + 10,40,30,false); //坦克的身体
- g.fillOval(x + 15,y + 10,30,30); //坦克的炮盖
- g.drawLine(x + 30,y + 25,x +60,y + 25); //坦克的炮筒
- break;
-
- case 2: //表示向下
- g.fill3DRect(x,y,10,60,false); //坦克的左边轮子
- g.drawLine(x,y + 10,x + 10,y + 10); //坦克左轮的履带
- g.drawLine(x,y + 20,x + 10,y + 20);
- g.drawLine(x,y + 30,x + 10,y + 30);
- g.drawLine(x,y + 40,x + 10,y + 40);
- g.drawLine(x,y + 50,x + 10,y + 50);
-
- g.fill3DRect(x + 40,y,10,60,false); //坦克的右边轮子
- g.drawLine(x + 40,y + 10,x + 50,y + 10); //坦克右轮的履带
- g.drawLine(x + 40,y + 20,x + 50,y + 20);
- g.drawLine(x + 40,y + 30,x + 50,y + 30);
- g.drawLine(x + 40,y + 40,x + 50,y + 40);
- g.drawLine(x + 40,y + 50,x + 50,y + 50);
-
- g.fill3DRect(x + 10,y + 10,30,40,false); //坦克的身体
- g.fillOval(x + 10,y + 15,30,30); //坦克的炮盖
- g.drawLine(x + 25,y + 30,x + 25,y + 60); //坦克的炮筒
- break;
-
- case 3: //表示向左
- g.fill3DRect(x,y,60,10,false); //坦克左边的轮子
- g.drawLine(x + 10,y,x + 10 ,y + 10); //坦克左轮的履带
- g.drawLine(x + 20,y,x + 20 ,y + 10);
- g.drawLine(x + 30,y,x + 30 ,y + 10);
- g.drawLine(x + 40,y,x + 40 ,y + 10);
- g.drawLine(x + 50,y,x + 50 ,y + 10);
-
-
- g.fill3DRect(x,y + 40,60,10,false); //坦克右边的轮子
- g.drawLine(x + 10,y + 40,x + 10,y + 50);
- g.drawLine(x + 20,y + 40,x + 20,y + 50);
- g.drawLine(x + 30,y + 40,x + 30,y + 50);
- g.drawLine(x + 40,y + 40,x + 40,y + 50);
- g.drawLine(x + 50,y + 40,x + 50,y + 50);
-
-
- g.fill3DRect( x + 10,y + 10,40,30,false); //坦克的身体
- g.fillOval(x + 15,y + 10,30,30); //坦克的炮盖
- g.drawLine(x + 30,y + 25,x,y + 25); //坦克的炮筒
- break;
-
- default:
- System.out.println("暂时没有处理");
- }
- }
-
- @Override
- public void keyTyped(KeyEvent e) {
-
- }
-
- @Override
- public void keyPressed(KeyEvent e) {
- if(e.getKeyCode() == KeyEvent.VK_W){
- myTank.setDirect(0);
- if(myTank.getY() > 0) {
- myTank.MoveUp();
- }
- }else if(e.getKeyCode() == KeyEvent.VK_D){
- myTank.setDirect(1);
- if(myTank.getX() + 60 < 1000) {
- myTank.MoveRight();
- }
- }else if(e.getKeyCode() == KeyEvent.VK_S){
- myTank.setDirect(2);
- if(myTank.getY() + 60 < 800) {
- myTank.MoveDown();
- }
- }else if(e.getKeyCode() == KeyEvent.VK_A){
- myTank.setDirect(3);
- if(myTank.getX() + 60 > 0) {
- myTank.MoveLeft();
- }
- }
- // else if(e.getKeyCode() == KeyEvent.VK_UP){
- // opTanks.get(0).setDirect(0);
- // opTanks.get(0).MoveUp();
- // }else if(e.getKeyCode() == KeyEvent.VK_RIGHT){
- // opTanks.get(0).setDirect(1);
- // opTanks.get(0).MoveRight();
- // }else if(e.getKeyCode() == KeyEvent.VK_DOWN){
- // opTanks.get(0).setDirect(2);
- // opTanks.get(0).MoveDown();
- // }else if(e.getKeyCode() == KeyEvent.VK_LEFT) {
- // opTanks.get(0).setDirect(3);
- // opTanks.get(0).MoveLeft();
- // }
-
-
- //如果玩家按下J键,我的坦克就会发出一个炮弹
- if(e.getKeyCode() == KeyEvent.VK_J){
- System.out.println("玩家按下了J键,开始射击!");
-
- myTank.shotOpTank();
- }
-
- this.repaint();
-
- }
-
- @Override
- public void keyReleased(KeyEvent e) {
-
- }
-
- @Override
- public void run() {
- while(true) {
- try {
- Thread.sleep(100);
- } catch (InterruptedException e) {
- e.printStackTrace();
- }
- //判断是否击中了敌人的坦克
- if(myTank.shot != null && myTank.shot.isLive){
- for(int i=0;i<opTanks.size();i++){ //遍历敌人的所有坦克
- HitTank(myTank.shot,opTanks.get(i));
- }
- }
-
-
- this.repaint();
- }
- }
-
- //编写方法判断炮弹是否打中坦克
- public void HitTank(Shot s,OpTank opTank){
- //判断是否击中坦克
- switch (opTank.getDirect()){
- case 0: //敌人坦克向上的方向
- case 2: //敌人坦克向下的方向
- if(s.x > opTank.getX() && s.x < opTank.getX() + 50 && s.y > opTank.getY() && s.y < opTank.getY() + 60){
- s.isLive = false;
- opTank.isLive = false;
- }
- break;
- case 1: //敌人坦克向右的方向
- case 3: //敌人坦克向左的方向
- if(s.x > opTank.getX() && s.x < opTank.getX() + 60 && s.y > opTank.getY() && s.y < opTank.getY() + 50){
- s.isLive = false;
- opTank.isLive = false;
- //当坦克被击中后将坦克从集合中移除
- opTanks.remove(opTank);
- }
- break;
- }
- }
-
- }

3.坦克基类(Tank)
- package com.wak.TankGame01Version;
-
- /*坦克的基类*/
- public class Tank {
- private int x; //坦克的横坐标
- private int y; //坦克的纵坐标
- private int direct = 0; //坦克的方向
- private int speed = 1; //坦克的速度
-
- public Tank(){
- this.x = 100; //默认坦克的初始x坐标为100
- this.y = 100; //默认坦克的初始y坐标为100
- }
-
- public Tank(int x,int y){ //自己设置坦克的初始x,y坐标
- this.x = x;
- this.y = y;
- }
-
-
- //设置坦克的x坐标
- public void setX(int x){
- this.x = x;
- }
-
- //设置坦克的y坐标
- public void setY(int y){
- this.y = y;
- }
-
- //获得坦克的x坐标
- public int getX(){
- return x;
- }
-
- //获得坦克的y坐标
- public int getY(){
- return y;
- }
-
- //设置坦克的方向
- public void setDirect(int direct){
- this.direct = direct;
- }
-
- //获得坦克的方向
- public int getDirect(){
- return direct;
- }
-
- //设置坦克的速度
- public void setSpeed(int speed){
- this.speed = speed;
- }
-
- //获得坦克的速度
- public int getSpeed(){
- return speed;
- }
-
- //坦克的上右下左移动
- public void MoveUp(){
- y -= speed;
- }
- public void MoveRight(){
- x += speed;
- }
- public void MoveDown(){
- y += speed;
- }
- public void MoveLeft(){
- x -= speed;
- }
- }
-
-

4.我的坦克类(MyTank)
- package com.wak.TankGame01Version;
-
- /*自己的坦克*/
- public class MyTank extends Tank{
- //创建一个坦克
- private MyTank myTank = null;
-
- Shot shot = null;
- //设置坦克的初始化坐标
- public MyTank(int x,int y){
- this.setX(x);
- this.setY(y);
- }
-
- //射击
- public void shotOpTank(){
- //设置炮弹的初始化坐标及方向
- switch (this.getDirect()){
- case 0:
- shot = new Shot(this.getX() + 25,this.getY(),0);
- break;
- case 1:
- shot = new Shot(this.getX() + 60,this.getY() + 25,1);
- break;
- case 2:
- shot = new Shot(this.getX() + 25,this.getY() + 60,2);
- break;
- case 3:
- shot = new Shot(this.getX(),this.getY() + 25,3);
- }
-
-
- //启动我们的Shot线程
- new Thread(shot).start();
- }
- }

5.敌方坦克类(OpTank)
- package com.wak.TankGame01Version;
-
- import java.util.Vector;
-
- public class OpTank extends Tank implements Runnable{
- private OpTank opTank = null; //创建一个敌方坦克
- boolean isLive = true; //敌方坦克的存活状态
- Vector<Shot> shots = new Vector<>(); //存储多个炮弹
-
- public OpTank(int x,int y){
- this.setX(x);
- this.setY(y);
- }
-
- @Override
- public void run() {
- while(true){
- switch (this.getDirect()){
- case 0:
- for(int i=0;i<80;i++) {
- if (getY() > 0){
- MoveUp();
- }
- //休眠
- try {
- Thread.sleep(50);
- } catch (InterruptedException e) {
- e.printStackTrace();
- }
- }
- break;
- case 1:
- for (int i=0;i<80;i++){
- if(getX() + 60< 1000) {
- MoveRight();
- }
- //休眠
- try {
- Thread.sleep(50);
- } catch (InterruptedException e) {
- e.printStackTrace();
- }
- }
- break;
- case 2:
- for (int i=0;i<80;i++){
- if(getY() + 60 < 1000) {
- MoveDown();
- }
- //休眠
- try {
- Thread.sleep(50);
- } catch (InterruptedException e) {
- e.printStackTrace();
- }
- }
- break;
- case 3:
- for (int i=0;i<80;i++){
- if(getY() + 60 < 800) {
- MoveLeft();
- }
- //休眠
- try {
- Thread.sleep(50);
- } catch (InterruptedException e) {
- e.printStackTrace();
- }
- }
- break;
- }
- setDirect((int)(Math.random() * 4));
- if(!isLive){
- break;
- }
- }
- }
- }

6.炮弹类(Shot)
- package com.wak.TankGame01Version;
-
- public class Shot implements Runnable{
- int x; //子弹的x坐标
- int y; //子弹的y坐标
- int direct = 0; //子弹的方向
- int speed = 2; //子弹的速度
- boolean isLive = true; //子弹的存活状态
-
- public Shot(int x,int y,int direct){
- this.x = x;
- this.y = y;
- this.direct = direct;
- }
-
- @Override
- public void run() { //射击
- while(isLive){
- //休眠
- try {
- Thread.sleep(50);
- } catch (InterruptedException 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;
- }
-
- System.out.println("炮弹的x坐标:" + x + ",炮弹的y坐标:" + y);
- //如果炮弹弹撞到墙壁,则销毁
- //当炮弹碰到敌人坦克时,也应当结束
- if(!(x >= 0 && x <= 1000 && y >=0 && y <= 800 && isLive)){
- isLive = false;
- System.out.println("炮弹已销毁");
- }
- }
- }
- }

运行效果截图:
小总结:今天完成了,坦克发射多颗炮弹,敌方坦克移动发射,我方坦克被炮弹击中,防止敌方坦克重叠,记录玩家成绩,记录敌人坦克信息。今天觉得比较有创新的点就是防止坦克重叠,还是以坦克的一个点出发,从坐标出发,这样思路就很明确。今天的一个小插曲是,最后韩老师还教了一个继续上局游戏的操作,但是,这个视频中,我发现,有很多内容之前都没学过,但是我先跟着敲了(这就为后面埋下了一个伏笔),结果当我正式运行的时候,开始新的游戏,是正常的,除了对记录击毁多少个敌人的次数,是上一局继承下来的(我觉得这个问题后面可以用一个if语句进行,清零操作),但是,当我继续上局游戏时,运行出来,敌方的坦克全部消失,然后我就又重新看视频,找问题,改了几个地方,发现越改越错,当时脑子直接懵了,然后我就一直Ctrl-Z,还好,最后改回来了,我本来想把这个内容加上去的,但是我发现以我现在的能力,我可以把这个时间去用来写一些跟游戏更贴切的内容,比如现在运行出来只有我的坦克和对面坦克,还没有掩体等,坦克的速度,初始位置,以及炮弹的速度,都还没有进行调试,相比于那个,这才是重点,这也是明天的内容。今天新增了一个Recorder类和一个Node类(记录坦克的位置信息等,但是由于后面的内容我没有继续再写了,这个类也就相当于白建的)。
以下是今天的代码记录截图:
七个类 (根据英文应该能猜到各自对应什么)
1.主程序类(TankGame01)
- package com.wak.TankGame01Version;
-
- import javax.swing.*;
- import java.awt.event.WindowAdapter;
- import java.awt.event.WindowEvent;
-
- /*坦克大战游戏主程序*/
- public class TankGame01 extends JFrame {
- public static void main(String[] args) {
- //启动!
- new TankGame01();
- }
-
- //定义GamePanel,创建游戏环境
- GamePanel gamePanel = null;
-
- //加载游戏环境
- public TankGame01(){
- //1.0版本
- this.setTitle("坦克大战1.0");
- //加载游戏环境
- gamePanel = new GamePanel();
- //将游戏区域加载到界面里
- this.add(gamePanel);
- //将游戏界面的炮弹线程加入到界面里
- Thread thread = new Thread(gamePanel);
- //启动子线程
- thread.start();
- //将键盘监听器加载到界面里
- this.addKeyListener(gamePanel);
- //设置界面可视化
- this.setVisible(true);
- //设置界面的大小
- this.setSize(1400,950);
- //设置界面可关闭
- this.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
-
- //在JFrame中增加相应关闭窗口的处理
- this.addWindowListener(new WindowAdapter() {
- @Override
- public void windowClosing(WindowEvent e) {
- Recorder.KeepRecord();
- System.exit(0);
- }
- });
- }
-
- }

2.游戏界面绘制类(GamePanel)
- package com.wak.TankGame01Version;
-
- import javax.swing.*;
- import java.awt.*;
- import java.awt.event.KeyEvent;
- import java.awt.event.KeyListener;
- import java.util.Vector;
-
- /*坦克大战的绘图区域*/
-
- //为了监听键盘事件,实现KeyListener
- //
- public class GamePanel extends JPanel implements KeyListener,Runnable{
- //定义一个自己的坦克
- MyTank myTank = null;
- //创建敌方坦克
- Vector<OpTank> opTanks = new Vector<>();
- //定义一个存放Node对象的Vector,用于恢复敌方坦克的坐标和方向
- Vector<Node> nodes = new Vector<>();
- //设置敌方坦克数量
- int opTanksSize = 6;
-
- public GamePanel(/*String key*/){
- // Recorder.getNodesAndEnemyTankRec();
- myTank = new MyTank(200,600); //初始化坦克的位置
- myTank.setSpeed(3); //设置坦克的速度
-
- //将GamePanel对象的 opTanks 设置给 Recorder 的 opTanks
- Recorder.setOpTanks(opTanks);
-
-
-
- for(int i=0;i<opTanksSize;i++){
- OpTank opTank = new OpTank((100 * i + 100),0);
- opTank.setOpTanks(opTanks);
- //设置方向
- opTank.setDirect(2);
- //启动敌人坦克线程
- new Thread(opTank).start();
- //给该opTank加入一颗炮弹
- Shot shot = new Shot(opTank.getX() + 25,opTank.getY() + 60,2);
- //存放到Vector中
- opTank.shots.add(shot);
- //启动线程对象
- new Thread(shot).start();
- //加入
- opTanks.add(opTank);
- }
-
- }
-
- //编写方法,显示我方击毁敌方坦克的信息
- public void showInfo(Graphics g){
- //画出玩家的总成绩
- g.setColor(Color.BLACK);
- Font font = new Font("宋体",Font.BOLD,25);
- g.setFont(font);
-
- g.drawString("您累计击毁敌方坦克的数量",1020,30);
- DrawTank(1020,60,g,0,1);
- g.setColor(Color.BLACK);
- g.drawString(Recorder.getAllOpTanksNum() + "",1080,100);
- }
-
-
-
- @Override
- public void paint(Graphics g) {
- super.paint(g);
- g.fillRect(0,0,1000,800); //默认背景是黑色
-
- showInfo(g);
- //画出坦克-封装方法
- //画出我的坦克
- if(myTank.isLive) {
- DrawTank(myTank.getX(), myTank.getY(), g, myTank.getDirect(), 0);
- }
- //画出敌人的坦克
- for(int i=0;i<opTanks.size();i++){
- //取出敌方坦克
- OpTank opTank = opTanks.get(i);
- //判断敌方坦克是否存活
- if(opTank.isLive) { //当敌人坦克是存活的时候,才去画
- DrawTank(opTank.getX(), opTank.getY(), g, opTank.getDirect(), 1);
- //画出敌人的坦克发出的炮弹
- for (int j = 0; j < opTank.shots.size(); j++) {
- //取出子弹
- Shot shot = opTank.shots.get(j);
- //绘制
- if (shot.isLive) {
- g.setColor(Color.WHITE);
- g.fill3DRect(shot.x, shot.y, 4, 4, false);
- } else {
- opTank.shots.remove(shot);
- }
- }
- }
-
- }
-
- //画出我的坦克发出的炮弹
- if(myTank.isLive) {
- for (int i = 0; i < myTank.shots.size(); i++) {
- if (myTank.shots.get(i) != null && myTank.shots.get(i).isLive == true) {
- g.setColor(Color.CYAN);
- g.fill3DRect(myTank.shots.get(i).x, myTank.shots.get(i).y, 4, 4, false);
- } else {
- myTank.shots.remove(i);
- }
- }
- }
-
- }
-
- //编写方法,画出坦克
-
- /**
- *
- * @param x 坦克的x坐标
- * @param y 坦克的y坐标
- * @param g 画笔
- * @param direct 坦克方向(上下左右)
- * @param type 坦克类型
- */
- public void DrawTank(int x,int y,Graphics g,int direct,int type){
- //坦克的类型
- switch (type){
- case 0: //自己的坦克
- g.setColor(Color.CYAN);
- break;
- case 1: //敌人的坦克
- g.setColor(Color.RED);
- break;
- }
-
- switch (direct){
- case 0: //表示向上
- g.fill3DRect(x,y,10,60,false); //坦克的左边轮子
- g.drawLine(x,y + 10,x + 10,y + 10); //坦克左轮的履带
- g.drawLine(x,y + 20,x + 10,y + 20);
- g.drawLine(x,y + 30,x + 10,y + 30);
- g.drawLine(x,y + 40,x + 10,y + 40);
- g.drawLine(x,y + 50,x + 10,y + 50);
-
- g.fill3DRect(x + 40,y,10,60,false); //坦克的右边轮子
- g.drawLine(x + 40,y + 10,x + 50,y + 10); //坦克右轮的履带
- g.drawLine(x + 40,y + 20,x + 50,y + 20);
- g.drawLine(x + 40,y + 30,x + 50,y + 30);
- g.drawLine(x + 40,y + 40,x + 50,y + 40);
- g.drawLine(x + 40,y + 50,x + 50,y + 50);
-
- g.fill3DRect(x + 10,y + 10,30,40,false); //坦克的身体
- g.fillOval(x + 10,y + 15,30,30); //坦克的炮盖
- g.drawLine(x + 25,y + 30,x + 25,y); //坦克的炮筒
- break;
-
- case 1: //表示向右
- g.fill3DRect(x,y,60,10,false); //坦克左边的轮子
- g.drawLine(x + 10,y,x + 10 ,y + 10); //坦克左轮的履带
- g.drawLine(x + 20,y,x + 20 ,y + 10);
- g.drawLine(x + 30,y,x + 30 ,y + 10);
- g.drawLine(x + 40,y,x + 40 ,y + 10);
- g.drawLine(x + 50,y,x + 50 ,y + 10);
-
-
- g.fill3DRect(x,y + 40,60,10,false); //坦克右边的轮子
- g.drawLine(x + 10,y + 40,x + 10,y + 50);
- g.drawLine(x + 20,y + 40,x + 20,y + 50);
- g.drawLine(x + 30,y + 40,x + 30,y + 50);
- g.drawLine(x + 40,y + 40,x + 40,y + 50);
- g.drawLine(x + 50,y + 40,x + 50,y + 50);
-
-
- g.fill3DRect( x + 10,y + 10,40,30,false); //坦克的身体
- g.fillOval(x + 15,y + 10,30,30); //坦克的炮盖
- g.drawLine(x + 30,y + 25,x +60,y + 25); //坦克的炮筒
- break;
-
- case 2: //表示向下
- g.fill3DRect(x,y,10,60,false); //坦克的左边轮子
- g.drawLine(x,y + 10,x + 10,y + 10); //坦克左轮的履带
- g.drawLine(x,y + 20,x + 10,y + 20);
- g.drawLine(x,y + 30,x + 10,y + 30);
- g.drawLine(x,y + 40,x + 10,y + 40);
- g.drawLine(x,y + 50,x + 10,y + 50);
-
- g.fill3DRect(x + 40,y,10,60,false); //坦克的右边轮子
- g.drawLine(x + 40,y + 10,x + 50,y + 10); //坦克右轮的履带
- g.drawLine(x + 40,y + 20,x + 50,y + 20);
- g.drawLine(x + 40,y + 30,x + 50,y + 30);
- g.drawLine(x + 40,y + 40,x + 50,y + 40);
- g.drawLine(x + 40,y + 50,x + 50,y + 50);
-
- g.fill3DRect(x + 10,y + 10,30,40,false); //坦克的身体
- g.fillOval(x + 10,y + 15,30,30); //坦克的炮盖
- g.drawLine(x + 25,y + 30,x + 25,y + 60); //坦克的炮筒
- break;
-
- case 3: //表示向左
- g.fill3DRect(x,y,60,10,false); //坦克左边的轮子
- g.drawLine(x + 10,y,x + 10 ,y + 10); //坦克左轮的履带
- g.drawLine(x + 20,y,x + 20 ,y + 10);
- g.drawLine(x + 30,y,x + 30 ,y + 10);
- g.drawLine(x + 40,y,x + 40 ,y + 10);
- g.drawLine(x + 50,y,x + 50 ,y + 10);
-
-
- g.fill3DRect(x,y + 40,60,10,false); //坦克右边的轮子
- g.drawLine(x + 10,y + 40,x + 10,y + 50);
- g.drawLine(x + 20,y + 40,x + 20,y + 50);
- g.drawLine(x + 30,y + 40,x + 30,y + 50);
- g.drawLine(x + 40,y + 40,x + 40,y + 50);
- g.drawLine(x + 50,y + 40,x + 50,y + 50);
-
-
- g.fill3DRect( x + 10,y + 10,40,30,false); //坦克的身体
- g.fillOval(x + 15,y + 10,30,30); //坦克的炮盖
- g.drawLine(x + 30,y + 25,x,y + 25); //坦克的炮筒
- break;
-
- default:
- System.out.println("暂时没有处理");
- }
- }
-
- @Override
- public void keyTyped(KeyEvent e) {
-
- }
-
- @Override
- public void keyPressed(KeyEvent e) { //控制键盘WDSA键,操控我的坦克上右下左移动
- if(e.getKeyCode() == KeyEvent.VK_W){
- myTank.setDirect(0);
- if(myTank.getY() > 0) {
- myTank.MoveUp();
- }
- }else if(e.getKeyCode() == KeyEvent.VK_D){
- myTank.setDirect(1);
- if(myTank.getX() + 60 < 1000) {
- myTank.MoveRight();
- }
- }else if(e.getKeyCode() == KeyEvent.VK_S){
- myTank.setDirect(2);
- if(myTank.getY() + 60 < 800) {
- myTank.MoveDown();
- }
- }else if(e.getKeyCode() == KeyEvent.VK_A){
- myTank.setDirect(3);
- if(myTank.getX() + 60 > 0) {
- myTank.MoveLeft();
- }
- }
- // else if(e.getKeyCode() == KeyEvent.VK_UP){
- // opTanks.get(0).setDirect(0);
- // opTanks.get(0).MoveUp();
- // }else if(e.getKeyCode() == KeyEvent.VK_RIGHT){
- // opTanks.get(0).setDirect(1);
- // opTanks.get(0).MoveRight();
- // }else if(e.getKeyCode() == KeyEvent.VK_DOWN){
- // opTanks.get(0).setDirect(2);
- // opTanks.get(0).MoveDown();
- // }else if(e.getKeyCode() == KeyEvent.VK_LEFT) {
- // opTanks.get(0).setDirect(3);
- // opTanks.get(0).MoveLeft();
- // }
-
-
- //如果玩家按下J键,我的坦克就会发出一个炮弹
- if(e.getKeyCode() == KeyEvent.VK_J){
- // System.out.println("玩家按下了J键,开始射击!");
- // if(myTank.shot == null || myTank.shot.isLive == false) { //当坦克只能发射一颗炮弹时,先判断
- // myTank.shotOpTank();
- // }
- myTank.shotOpTank();
- }
-
- this.repaint();
-
- }
-
- @Override
- public void keyReleased(KeyEvent e) {
-
- }
-
- @Override
- public void run() {
- while(true) {
- try {
- Thread.sleep(100);
- } catch (InterruptedException e) {
- e.printStackTrace();
- }
- //判断是否击中了敌人的坦克
- for(int j=0;j<myTank.shots.size();j++) {
- if (myTank.shots.get(j) != null && myTank.shots.get(j).isLive) {
- for (int i = 0; i < opTanks.size(); i++) { //遍历敌人的所有坦克
- HitTank(myTank.shots.get(j), opTanks.get(i));
- }
- }
- }
- HitMyTank();
- this.repaint();
- }
- }
-
- //编写方法判断敌方坦克的炮弹是否打中我的坦克
- public void HitMyTank(){
- for(int i=0;i<opTanks.size();i++){
- for(int j=0;j<opTanks.get(i).shots.size();j++){
- if(myTank.isLive && opTanks.get(i).shots.get(j).isLive){
- HitTank(opTanks.get(i).shots.get(j),myTank);
- }
- }
- }
- }
-
-
- //编写方法判断炮弹是否打中坦克
- public void HitTank(Shot s,Tank opTank){
- //判断是否击中坦克
- switch (opTank.getDirect()){
- case 0: //敌人坦克向上的方向
- case 2: //敌人坦克向下的方向
- if(s.x > opTank.getX() && s.x < opTank.getX() + 50 && s.y > opTank.getY() && s.y < opTank.getY() + 60){
- s.isLive = false;
- opTank.isLive = false;
- //当坦克被击中后将坦克从集合中移除
- opTanks.remove(opTank);
- //解读,因为opTank可以是没有Tank,也可以是opTank
- if(opTank instanceof OpTank){
- Recorder.addAllOpTanksNum();
- }
- }
- break;
- case 1: //敌人坦克向右的方向
- case 3: //敌人坦克向左的方向
- if(s.x > opTank.getX() && s.x < opTank.getX() + 60 && s.y > opTank.getY() && s.y < opTank.getY() + 50){
- s.isLive = false;
- opTank.isLive = false;
- //当坦克被击中后将坦克从集合中移除
- opTanks.remove(opTank);
- //解读,因为opTank可以是没有Tank,也可以是opTank
- if(opTank instanceof OpTank){
- Recorder.addAllOpTanksNum();
- }
- }
- break;
- }
- }
-
- }

3.坦克基类(Tank)
- package com.wak.TankGame01Version;
-
- /*坦克的基类*/
- public class Tank {
- private int x; //坦克的横坐标
- private int y; //坦克的纵坐标
- private int direct = 0; //坦克的方向
- private int speed = 1; //坦克的速度
- boolean isLive = true; //坦克的存活状态
-
- public Tank(){
- this.x = 100; //默认坦克的初始x坐标为100
- this.y = 100; //默认坦克的初始y坐标为100
- }
-
- public Tank(int x,int y){ //自己设置坦克的初始x,y坐标
- this.x = x;
- this.y = y;
- }
-
-
- //设置坦克的x坐标
- public void setX(int x){
- this.x = x;
- }
-
- //设置坦克的y坐标
- public void setY(int y){
- this.y = y;
- }
-
- //获得坦克的x坐标
- public int getX(){
- return x;
- }
-
- //获得坦克的y坐标
- public int getY(){
- return y;
- }
-
- //设置坦克的方向
- public void setDirect(int direct){
- this.direct = direct;
- }
-
- //获得坦克的方向
- public int getDirect(){
- return direct;
- }
-
- //设置坦克的速度
- public void setSpeed(int speed){
- this.speed = speed;
- }
-
- //获得坦克的速度
- public int getSpeed(){
- return speed;
- }
-
- //坦克的上右下左移动
- public void MoveUp(){
- y -= speed;
- }
- public void MoveRight(){
- x += speed;
- }
- public void MoveDown(){
- y += speed;
- }
- public void MoveLeft(){
- x -= speed;
- }
- }
-
-

4.我的坦克类(MyTank)
- package com.wak.TankGame01Version;
-
- import java.util.Vector;
-
- /*自己的坦克*/
- public class MyTank extends Tank{
-
- //创建一个坦克
- private MyTank myTank = null;
-
- //定义一个shot对象,表示一个射击(线程)
- Shot shot = null;
- //创建一个存储炮弹的集合
- Vector<Shot> shots = new Vector<>();
- //设置坦克的初始化坐标
- public MyTank(int x,int y){
- this.setX(x);
- this.setY(y);
- }
-
- //射击
- public void shotOpTank(){
- //设置炮弹的初始化坐标及方向
- if(shots.size() < 5) {
- switch (this.getDirect()) {
- case 0:
- shot = new Shot(this.getX() + 25, this.getY(), 0);
- break;
- case 1:
- shot = new Shot(this.getX() + 60, this.getY() + 25, 1);
- break;
- case 2:
- shot = new Shot(this.getX() + 25, this.getY() + 60, 2);
- break;
- case 3:
- shot = new Shot(this.getX(), this.getY() + 25, 3);
- }
- //将发射的炮弹弹存入集合中
-
- shots.add(shot);
- }
- //启动我们的Shot线程
- new Thread(shot).start();
-
- }
- }

5.敌方坦克类(OpTank)
- package com.wak.TankGame01Version;
-
- import java.util.Vector;
-
- public class OpTank extends Tank implements Runnable{
- private OpTank opTank = null; //创建一个敌方坦克
- Vector<Shot> shots = new Vector<>(); //存储多个炮弹
- Vector<OpTank> opTanks = new Vector<>(); //增加成员,可以得到敌人坦克的Vector集合
- public OpTank(int x,int y){
- this.setX(x);
- this.setY(y);
- }
-
- public void setOpTanks(Vector<OpTank> opTanks){
- this.opTanks = opTanks;
- }
-
- public boolean isTouchOpTank(){
- //判断当前敌人坦克的方向
- switch (this.getDirect()){
- case 0: //上
- for(int j=0;j<opTanks.size();j++){
- //取出一个敌方坦克
- OpTank o = opTanks.get(j);
- if(o != this){ //不能跟自己比
- //如果敌人是向上或者向下
- if(o.getDirect() == 0 || o.getDirect() == 2){
- //当前坦克左上角的坐标
- if(this.getX() >= o.getX()
- && this.getX() <= o.getX() + 50
- && this.getY() <= o.getY() + 60
- && this.getY() >= o.getY()){
- return true;
- }
- //当前坦克右上角的坐标
- if(this.getX() + 50 >= o.getX()
- && this.getX() + 50<= o.getX() + 50
- && this.getY() <= o.getY() + 60
- && this.getY() >= o.getY()){
- return true;
- }
- }
- //如果敌人是向右或者向左
- if(o.getDirect() == 1 || o.getDirect() == 3){
- //当前坦克左上角的坐标
- if(this.getX() >= o.getX()
- && this.getX() <= o.getX() + 60
- && this.getY() >= o.getY()
- && this.getY() <= o.getY() + 50){
- return true;
- }
- //当前坦克右上角的坐标
- if(this.getX() + 50>= o.getX()
- && this.getX() + 50<= o.getX() + 60
- && this.getY() >= o.getY()
- && this.getY() <= o.getY() + 50){
- return true;
- }
- }
- }
- }
- break;
- case 1: //右
- for(int j=0;j<opTanks.size();j++){
- //取出一辆坦克
- OpTank o = opTanks.get(j);
- if(o != this){ //不能跟自己比
- //如果敌方坦克是向上或向下
- if(o.getDirect() == 0 || o.getDirect() == 2){
- //当前坦克右上角的坐标
- if(this.getX() + 60 >= o.getX()
- && this.getX() + 60 <= o.getX() + 50
- && this.getY() >= o.getY()
- && this.getY() <= o.getY() + 60){
- return true;
- }
- //当前坦克右下角的坐标
- if(this.getX() + 60 >= o.getX()
- && this.getX() + 60 <= o.getX() + 50
- && this.getY() + 50 >= o.getY()
- && this.getY() + 50 <= o.getY() + 60){
- return true;
- }
- }
- //如果敌方坦克是向右或向左
- if(o.getDirect() == 1 || o.getDirect() == 3){
- //当前坦克右上角的坐标
- if(this.getX() + 60 >= o.getX()
- && this.getX() + 60 <= o.getX() + 60
- && this.getY() >= o.getY()
- && this.getY() <= o.getY() + 50){
- return true;
- }
- //当前坦克右下角的坐标
- if(this.getX() + 60 >= o.getX()
- && this.getX() + 60 <= o.getX() + 60
- && this.getY() + 50 >= o.getY()
- && this.getY() + 50 <= o.getY() + 50){
- return true;
- }
- }
- }
- }
- break;
- case 2: //下
- for(int j=0;j<opTanks.size();j++){
- //取出一辆坦克
- OpTank o = opTanks.get(j);
- if(o != this){ //不能跟自己比
- //如果敌方坦克是向上或向下
- if(o.getDirect() == 0 || o.getDirect() == 2){
- //当前坦克左下角的坐标
- if(this.getX() >= o.getX()
- && this.getX() <= o.getX() + 60
- && this.getY() + 60 >= o.getY()
- && this.getY() + 60 <= o.getY()){
- return true;
- }
- //当前坦克右下角的坐标
- if(this.getX() + 50>= o.getX()
- && this.getX() + 50 <= o.getX() + 60
- && this.getY() + 60 >= o.getY()
- && this.getY() + 60 <= o.getY()){
- return true;
- }
- }
- //如果敌方坦克是向右或向左
- if(o.getDirect() == 1 || o.getDirect() == 3){
- //当前坦克左下角的坐标
- if(this.getX() >= o.getX()
- && this.getX() + 60 <= o.getX() + 60
- && this.getY() >= o.getY()
- && this.getY() + 50 <= o.getY() + 50){
- return true;
- }
- //当前坦克右下角的坐标
- if(this.getX() + 50 >= o.getX()
- && this.getX() + 50 <= o.getX() + 60
- && this.getY() + 60 >= o.getY()
- && this.getY() + 60 <= o.getY() + 50){
- return true;
- }
- }
- }
- }
- break;
- case 3: //左
- for(int j=0;j<opTanks.size();j++){
- //取出一辆坦克
- OpTank o = opTanks.get(j);
- if(o != this){ //不能跟自己比
- //如果敌方坦克是向上或向下
- if(o.getDirect() == 0 || o.getDirect() == 2){
- //当前坦克左上角的坐标
- if(this.getX() >= o.getX()
- && this.getX() <= o.getX() + 60
- && this.getY() >= o.getY()
- && this.getY() <= o.getY()){
- return true;
- }
- //当前坦克左下角的坐标
- if(this.getX() >= o.getX()
- && this.getX() <= o.getX() + 60
- && this.getY() + 50 >= o.getY()
- && this.getY() + 50 <= o.getY()){
- return true;
- }
- }
- //如果敌方坦克是向右或向左
- if(o.getDirect() == 1 || o.getDirect() == 3){
- //当前坦克左上角的坐标
- if(this.getX() >= o.getX()
- && this.getX() <= o.getX() + 60
- && this.getY() >= o.getY()
- && this.getY() <= o.getY() + 50){
- return true;
- }
- //当前坦克左下角的坐标
- if(this.getX() >= o.getX()
- && this.getX() <= o.getX() + 60
- && this.getY() + 50 >= o.getY()
- && this.getY() + 50 <= o.getY() + 50){
- return true;
- }
- }
- }
- }
- break;
- }
- return false;
- }
-
- @Override
- public void run() {
- while(true){
-
- //这里判断坦克的方向,创建对应的炮弹
- if(isLive && shots.size() < 6){
- Shot s = null;
- switch (getDirect()){
- case 0:
- s = new Shot(getX() + 25,getY(),0);
- break;
- case 1:
- s = new Shot(getX() + 60,getY() + 25,1);
- break;
- case 2:
- s = new Shot(getX() + 25,getY() + 60,2);
- break;
- case 3:
- s = new Shot(getX(),getY() + 25,3);
- break;
- }
-
- //每隔1秒发射一个炮弹
- try {
- Thread.sleep(2000);
- } catch (InterruptedException e) {
- e.printStackTrace();
- }
-
- shots.add(s);
-
- new Thread(s).start();
- }
- //坦克移动的方向
- switch (this.getDirect()){
- case 0:
- for(int i=0;i<80;i++) {
- if (getY() > 0 && !isTouchOpTank()){
- MoveUp();
- }
- //休眠
- try {
- Thread.sleep(50);
- } catch (InterruptedException e) {
- e.printStackTrace();
- }
- }
- break;
- case 1:
- for (int i=0;i<80;i++){
- if(getX() + 60< 1000 && !isTouchOpTank()) {
- MoveRight();
- }
- //休眠
- try {
- Thread.sleep(50);
- } catch (InterruptedException e) {
- e.printStackTrace();
- }
- }
- break;
- case 2:
- for (int i=0;i<80;i++){
- if(getY() + 60 < 800 && !isTouchOpTank()) {
- MoveDown();
- }
- //休眠
- try {
- Thread.sleep(50);
- } catch (InterruptedException e) {
- e.printStackTrace();
- }
- }
- break;
- case 3:
- for (int i=0;i<80;i++){
- if(getX() > 0 && !isTouchOpTank()) {
- MoveLeft();
- }
- //休眠
- try {
- Thread.sleep(50);
- } catch (InterruptedException e) {
- e.printStackTrace();
- }
- }
- break;
- }
- setDirect((int)(Math.random() * 4));
- if(!isLive){
- break;
- }
- }
- }
- }

6.炮弹类(Shot)
- package com.wak.TankGame01Version;
-
- public class Shot implements Runnable{
- int x; //子弹的x坐标
- int y; //子弹的y坐标
- int direct = 0; //子弹的方向
- int speed = 2; //子弹的速度
- boolean isLive = true; //子弹的存活状态
-
- public Shot(int x,int y,int direct){
- this.x = x;
- this.y = y;
- this.direct = direct;
- }
-
- @Override
- public void run() { //射击
- while(isLive){
- //休眠
- try {
- Thread.sleep(50);
- } catch (InterruptedException 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;
- }
-
- System.out.println("炮弹的x坐标:" + x + ",炮弹的y坐标:" + y);
- //如果炮弹弹撞到墙壁,则销毁
- //当炮弹碰到敌人坦克时,也应当结束
- if(!(x >= 0 && x <= 1000 && y >=0 && y <= 800 && isLive)){
- isLive = false;
- System.out.println("炮弹已销毁");
- }
- }
- }
- }

7.记录信息类(Recorder)
- package com.wak.TankGame01Version;
-
- import java.awt.*;
- import java.io.*;
- import java.util.Vector;
-
- public class Recorder {
- private static int allOpTanksNum = 0;
- //定义IO对象,准备写数据到文件中
- private static FileWriter fw = null;
- private static BufferedWriter bw = null;
- private static BufferedReader br = null;
- private static String recordFile = "D:\\myTankGameRecord.txt";
- //定义Vec,指向GamePanel对象的 敌人坦克Vector
- private static Vector<OpTank> opTanks = null;
- //定义一个Node 的Vector,用于保存敌人的信息node
- private static Vector<Node> nodes = new Vector<>();
-
- public static void setOpTanks(Vector<OpTank> opTanks){
- Recorder.opTanks = opTanks;
- }
-
- public static int getAllOpTanksNum(){
- return allOpTanksNum;
- }
-
- public static void setAllOpTanksNum(int allOpTanksNum){
- Recorder.allOpTanksNum = allOpTanksNum;
- }
-
-
- //当我方坦克击毁一个敌人坦克,就应当allOpTanksNum++
- public static void addAllOpTanksNum(){
- Recorder.allOpTanksNum++;
- }
-
- //增加一个方法,当游戏退出时,我们将allOpTanksNum保存到recordFile
- //对KeepRecord方法进行升级,保存敌人坦克的坐标和方向
- public static void KeepRecord(){
- try {
- bw = new BufferedWriter((new FileWriter((recordFile))));
- bw.write(allOpTanksNum + "\r\n");
- //遍历敌人坦克的Vector,然后根据情况保存即可
- for(int i=0;i<opTanks.size();i++){
- //取出敌人坦克
- OpTank o = opTanks.get(i);
- if(o.isLive){
- //保存该opTank的信息
- String record = o.getX() + " " + o.getY() + " " + o.getDirect();
- //写入到文件
- bw.write(record + "\r\n");
- }
- }
- } catch (IOException e) {
- e.printStackTrace();
- }finally {
- if (bw != null) {
- try {
- bw.close();
- } catch (IOException e) {
- e.printStackTrace();
- }
- }
- }
- }
-
- // //增加一个方法,用于读取recordFile,恢复相关信息
- // public static Vector<Node> getNodesAndEnemyTankRec(){
- // try {
- // br = new BufferedReader(new FileReader(recordFile));
- //
- // } catch (FileNotFoundException e) {
- // e.printStackTrace();
- // }finally {
- //
- // }
- // return null;
- // }
- }

运行效果截图:
小总结:今天完成了界面画面的布置,包括画了一条小河,草地,和障碍物(墙体),以及坦克碰到障碍物会停止前进,炮弹打到墙壁会销毁。今天真的是写这个项目这么久来,让我最印象深刻的一次今天,我在写完障碍物,遇到一个问题(当时没有截图或者录视频保存下来,可惜的是),就是我在离界面顶部Y坐标为100的位置时,坦克只会在这个Y坐标为0到100的范围内移动,于是我就觉得很奇怪,然后我就强制让他们只能朝下移动,结果发现,到了Y坐标等于100这个线的时候,所有的坦克全都不动了,只是发射炮弹,不会再继续往下移动。我又重新看了一遍我的方法,没有问题,于是我只好找学长求助,因为当我让他们自由可以改变方向移动时,他们能突破Y坐标为100的这条我暂且称之为“诡异线”,因为学长们对我的代码也不是特别熟悉,所以他们也没有给出一个正确答案,然后我就去找我之前的大四室友(已经在苏宁易购工作了),在通过测试时,我们发现一个问题,因为我是设置的六个坦克,从左到右依次排开,初始化他们是先向下移动的,当移动完之后,有一个坦克正好碰到了障碍物,而其他的没有,于是我们就猜测是不是这个影响了其他坦克,于是我们就把这个前面是障碍物的坦克删除掉,但是还是不行,我们最后只测试一个,发现这个坦克就可以突破这个“诡异线”,于是我想到了,就算把那个正好碰到坦克的障碍物删除,但是有一个坦克的右下角,与障碍物的一个角挨着了,因为我的判断是够与墙壁碰撞的判断条件,是写的大于等于,或者小于等于,就是这个等号,让代码运行过程有问题,后来总结出,尤其是在写这种游戏时,有的边界条件不能卡的太死,要不然就会出问题,因为这个毕竟是像素块,说不定就有个时候,越过了这个边界,然后就卡住了。但是由于是第一次写,还有很多知识点没有完全掌握好,所以当解决完这个问题后,整个人真的是,或许这就是代码的魅力吧!
以下是今天的代码记录截图:
七个类(根据英文应该能猜到各自对应什么)
1.主程序类(TankGame01)
- package com.wak.TankGame01Version;
-
- import javax.swing.*;
- import java.awt.event.WindowAdapter;
- import java.awt.event.WindowEvent;
-
- /*坦克大战游戏主程序*/
- public class TankGame01 extends JFrame {
- public static void main(String[] args) {
- //启动!
- new TankGame01();
- }
-
- //定义GamePanel,创建游戏环境
- GamePanel gamePanel = null;
-
- //加载游戏环境
- public TankGame01(){
- //1.0版本
- this.setTitle("坦克大战1.0");
- //加载游戏环境
- gamePanel = new GamePanel();
- //将游戏区域加载到界面里
- this.add(gamePanel);
- //将游戏界面的炮弹线程加入到界面里
- Thread thread = new Thread(gamePanel);
- //启动子线程
- thread.start();
- //将键盘监听器加载到界面里
- this.addKeyListener(gamePanel);
- //设置界面可视化
- this.setVisible(true);
- //设置界面的大小
- this.setSize(1600,950);
- //设置界面可关闭
- this.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
-
- //在JFrame中增加相应关闭窗口的处理
- this.addWindowListener(new WindowAdapter() {
- @Override
- public void windowClosing(WindowEvent e) {
- Recorder.KeepRecord();
- System.exit(0);
- }
- });
- }
-
- }

2.游戏界面绘制类(GamePanel)
- package com.wak.TankGame01Version;
-
- import javax.swing.*;
- import java.awt.*;
- import java.awt.event.KeyEvent;
- import java.awt.event.KeyListener;
- import java.util.Vector;
-
- /*坦克大战的绘图区域*/
-
- //为了监听键盘事件,实现KeyListener
- //
- public class GamePanel extends JPanel implements KeyListener,Runnable{
- //定义一个自己的坦克
- MyTank myTank = null;
- //创建敌方坦克
- Vector<OpTank> opTanks = new Vector<>();
- //定义一个存放Node对象的Vector,用于恢复敌方坦克的坐标和方向
- Vector<Node> nodes = new Vector<>();
- //设置敌方坦克数量
- int opTanksSize = 6;
-
- public GamePanel(/*String key*/){
- // Recorder.getNodesAndEnemyTankRec();
- myTank = new MyTank(580,810); //初始化我的坦克的位置
- myTank.setSpeed(3); //设置我的坦克的速度
- // myTank.shot.setShotSpeed(5); //设置我的坦克的炮弹的速度
-
- //将GamePanel对象的 opTanks 设置给 Recorder 的 opTanks
- Recorder.setOpTanks(opTanks);
-
-
- //初始化敌方坦克
- for(int i=0;i<opTanksSize;i++){
- OpTank opTank = new OpTank((200 * i + 90),0);
- opTank.setOpTanks(opTanks);
- //设置方向
- opTank.setDirect(2);
- //设置敌人坦克的速度
- opTank.setSpeed(1);
- //启动敌人坦克线程
- new Thread(opTank).start();
- //给该opTank加入一颗炮弹
- Shot shot = new Shot(opTank.getX() + 25,opTank.getY() + 60,2);
- //存放到Vector中
- opTank.shots.add(shot);
- //启动线程对象
- new Thread(shot).start();
- //加入
- opTanks.add(opTank);
- }
-
- }
-
- //编写方法,显示我方击毁敌方坦克的信息
- public void showInfo(Graphics g){
- //画出玩家的总成绩
- g.setColor(Color.BLACK);
- Font font = new Font("宋体",Font.BOLD,25);
- g.setFont(font);
-
- g.drawString("您累计击毁敌方坦克的数量",1220,30);
- DrawTank(1220,60,g,0,1);
- g.setColor(Color.BLACK);
- g.drawString(Recorder.getAllOpTanksNum() + "",1280,100);
- }
-
-
-
- @Override
- public void paint(Graphics g) {
- super.paint(g);
- g.fillRect(0,0,1200,900); //默认背景是黑色
-
- //设置背景为蓝色,代表河流
- g.setColor(Color.cyan);
- g.fill3DRect(100,400,1000,200,false);
-
- //设置背景为绿色,代表草地
- g.setColor(Color.GREEN);
- for(int i=0;i<7;i++) {
- g.fill3DRect(15 * i,100,5,600,false);
- g.fill3DRect(1100 + 15 * i,100,5,600,false);
- }
- for(int i=0;i<41;i++) {
- g.fill3DRect(0,100 + 15 * i,95,5,false);
- g.fill3DRect(1100,100 + 15 * i,95,5,false);
- }
-
- //设置背景为亮灰色,代表墙体
- g.setColor(Color.LIGHT_GRAY);
-
- g.fill3DRect(500,660,200,50,false);
- for(int i=1;i<5;i++) {
- g.drawLine(500, 660 + i*10, 700, 660 + i*10);
- }
- for(int i=1;i<20;i++){
- g.drawLine(500 + i*10,660,500 + i*10,710);
- }
-
- g.fill3DRect(260,660,60,130,false);
- for(int i=1;i<6;i++){
- g.drawLine(260 + i*10,660,260 + i*10,790);
- }
- for(int i=1;i<13;i++){
- g.drawLine(260,660 + i*10,320,660 + i*10);
- }
-
- g.fill3DRect(880,660,60,130,false);
- for(int i=1;i<6;i++){
- g.drawLine(880 + i*10,660,880 + i*10,790);
- }
- for(int i=1;i<13;i++){
- g.drawLine(880,660 + i*10,940,660 + i*10);
- }
-
- g.fill3DRect(350,100,60,240,false);
- for(int i=1;i<6;i++){
- g.drawLine(350 + i*10,100,350 + i*10,340);
- }
- for(int i=1;i<24;i++){
- g.drawLine(350,100 + i*10,410,100 + i*10);
- }
-
- g.fill3DRect(790,100,60,240,false);
- for(int i=1;i<6;i++){
- g.drawLine(790 + i*10,100,790 + i*10,340);
- }
- for(int i=1;i<24;i++){
- g.drawLine(790,100 + i*10,850,100 + i*10);
- }
-
- g.fill3DRect(550,160,100,100,false);
- for(int i=1;i<10;i++){
- g.drawLine(550 + i*10,160 ,550 + i*10,260);
- }
- for(int i=1;i<10;i++){
- g.drawLine(550,160 + i*10,650,160 + i*10);
- }
-
- // g.fill3DRect(160,100,130,60,false);
- // for(int i=1;i<13;i++){
- // g.drawLine(160 + i*10,100,160 + i*10,160);
- // }
- // for(int i=1;i<6;i++){
- // g.drawLine(160,100 + i*10,290,100 + i*10);
- // }
-
- // g.fill3DRect(910,100,130,60,false);
- // for(int i=1;i<13;i++){
- // g.drawLine(910 + i*10,100,910 + i*10,160);
- // }
- // for(int i=1;i<6;i++){
- // g.drawLine(910,100 + i*10,1040,100 + i*10);
- // }
-
-
- showInfo(g);
- //画出坦克-封装方法
- //画出我的坦克
- if(myTank.isLive) {
- DrawTank(myTank.getX(), myTank.getY(), g, myTank.getDirect(), 0);
- }
- //画出敌人的坦克
- for(int i=0;i<opTanks.size();i++){
- //取出敌方坦克
- OpTank opTank = opTanks.get(i);
- //判断敌方坦克是否存活
- if(opTank.isLive) { //当敌人坦克是存活的时候,才去画
- DrawTank(opTank.getX(), opTank.getY(), g, opTank.getDirect(), 1);
- //画出敌人的坦克发出的炮弹
- for (int j = 0; j < opTank.shots.size(); j++) {
- //取出子弹
- Shot shot = opTank.shots.get(j);
- //绘制
- if (shot.isLive) {
- g.setColor(Color.RED);
- g.fill3DRect(shot.x, shot.y, 4, 4, true);
- } else {
- opTank.shots.remove(shot);
- }
- }
- }
-
- }
-
- //画出我的坦克发出的炮弹
- if(myTank.isLive) {
- for (int i = 0; i < myTank.shots.size(); i++) {
- if (myTank.shots.get(i) != null && myTank.shots.get(i).isLive == true) {
- g.setColor(Color.YELLOW);
- g.fill3DRect(myTank.shots.get(i).x, myTank.shots.get(i).y, 4, 4, false);
- } else {
- myTank.shots.remove(i);
- }
- }
- }
-
- }
-
- //编写方法,画出坦克
-
- /**
- *
- * @param x 坦克的x坐标
- * @param y 坦克的y坐标
- * @param g 画笔
- * @param direct 坦克方向(上下左右)
- * @param type 坦克类型
- */
- public void DrawTank(int x,int y,Graphics g,int direct,int type){
- //坦克的类型
- switch (type){
- case 0: //自己的坦克
- g.setColor(Color.PINK);
- break;
- case 1: //敌人的坦克
- g.setColor(Color.RED);
- break;
- }
-
- switch (direct){
- case 0: //表示向上
- g.fill3DRect(x,y,10,60,false); //坦克的左边轮子
- g.drawLine(x,y + 10,x + 10,y + 10); //坦克左轮的履带
- g.drawLine(x,y + 20,x + 10,y + 20);
- g.drawLine(x,y + 30,x + 10,y + 30);
- g.drawLine(x,y + 40,x + 10,y + 40);
- g.drawLine(x,y + 50,x + 10,y + 50);
-
- g.fill3DRect(x + 40,y,10,60,false); //坦克的右边轮子
- g.drawLine(x + 40,y + 10,x + 50,y + 10); //坦克右轮的履带
- g.drawLine(x + 40,y + 20,x + 50,y + 20);
- g.drawLine(x + 40,y + 30,x + 50,y + 30);
- g.drawLine(x + 40,y + 40,x + 50,y + 40);
- g.drawLine(x + 40,y + 50,x + 50,y + 50);
-
- g.fill3DRect(x + 10,y + 10,30,40,false); //坦克的身体
- g.fillOval(x + 10,y + 15,30,30); //坦克的炮盖
- g.drawLine(x + 25,y + 30,x + 25,y); //坦克的炮筒
- break;
-
- case 1: //表示向右
- g.fill3DRect(x,y,60,10,false); //坦克左边的轮子
- g.drawLine(x + 10,y,x + 10 ,y + 10); //坦克左轮的履带
- g.drawLine(x + 20,y,x + 20 ,y + 10);
- g.drawLine(x + 30,y,x + 30 ,y + 10);
- g.drawLine(x + 40,y,x + 40 ,y + 10);
- g.drawLine(x + 50,y,x + 50 ,y + 10);
-
-
- g.fill3DRect(x,y + 40,60,10,false); //坦克右边的轮子
- g.drawLine(x + 10,y + 40,x + 10,y + 50);
- g.drawLine(x + 20,y + 40,x + 20,y + 50);
- g.drawLine(x + 30,y + 40,x + 30,y + 50);
- g.drawLine(x + 40,y + 40,x + 40,y + 50);
- g.drawLine(x + 50,y + 40,x + 50,y + 50);
-
-
- g.fill3DRect( x + 10,y + 10,40,30,false); //坦克的身体
- g.fillOval(x + 15,y + 10,30,30); //坦克的炮盖
- g.drawLine(x + 30,y + 25,x +60,y + 25); //坦克的炮筒
- break;
-
- case 2: //表示向下
- g.fill3DRect(x,y,10,60,false); //坦克的左边轮子
- g.drawLine(x,y + 10,x + 10,y + 10); //坦克左轮的履带
- g.drawLine(x,y + 20,x + 10,y + 20);
- g.drawLine(x,y + 30,x + 10,y + 30);
- g.drawLine(x,y + 40,x + 10,y + 40);
- g.drawLine(x,y + 50,x + 10,y + 50);
-
- g.fill3DRect(x + 40,y,10,60,false); //坦克的右边轮子
- g.drawLine(x + 40,y + 10,x + 50,y + 10); //坦克右轮的履带
- g.drawLine(x + 40,y + 20,x + 50,y + 20);
- g.drawLine(x + 40,y + 30,x + 50,y + 30);
- g.drawLine(x + 40,y + 40,x + 50,y + 40);
- g.drawLine(x + 40,y + 50,x + 50,y + 50);
-
- g.fill3DRect(x + 10,y + 10,30,40,false); //坦克的身体
- g.fillOval(x + 10,y + 15,30,30); //坦克的炮盖
- g.drawLine(x + 25,y + 30,x + 25,y + 60); //坦克的炮筒
- break;
-
- case 3: //表示向左
- g.fill3DRect(x,y,60,10,false); //坦克左边的轮子
- g.drawLine(x + 10,y,x + 10 ,y + 10); //坦克左轮的履带
- g.drawLine(x + 20,y,x + 20 ,y + 10);
- g.drawLine(x + 30,y,x + 30 ,y + 10);
- g.drawLine(x + 40,y,x + 40 ,y + 10);
- g.drawLine(x + 50,y,x + 50 ,y + 10);
-
-
- g.fill3DRect(x,y + 40,60,10,false); //坦克右边的轮子
- g.drawLine(x + 10,y + 40,x + 10,y + 50);
- g.drawLine(x + 20,y + 40,x + 20,y + 50);
- g.drawLine(x + 30,y + 40,x + 30,y + 50);
- g.drawLine(x + 40,y + 40,x + 40,y + 50);
- g.drawLine(x + 50,y + 40,x + 50,y + 50);
-
-
- g.fill3DRect( x + 10,y + 10,40,30,false); //坦克的身体
- g.fillOval(x + 15,y + 10,30,30); //坦克的炮盖
- g.drawLine(x + 30,y + 25,x,y + 25); //坦克的炮筒
- break;
-
- default:
- System.out.println("暂时没有处理");
- }
- }
-
- @Override
- public void keyTyped(KeyEvent e) {
-
- }
-
- @Override
- public void keyPressed(KeyEvent e) { //控制键盘WDSA键,操控我的坦克上右下左移动
- if(e.getKeyCode() == KeyEvent.VK_W){
- myTank.setDirect(0);
- if(myTank.getY() > 0 && !isMyTankTouchWall()) {
- myTank.MoveUp();
- }
- }else if(e.getKeyCode() == KeyEvent.VK_D){
- myTank.setDirect(1);
- if(myTank.getX() + 60 < 1200 && !isMyTankTouchWall()) {
- myTank.MoveRight();
- }
- }else if(e.getKeyCode() == KeyEvent.VK_S){
- myTank.setDirect(2);
- if(myTank.getY() + 60 < 900 && !isMyTankTouchWall()) {
- myTank.MoveDown();
- }
- }else if(e.getKeyCode() == KeyEvent.VK_A){
- myTank.setDirect(3);
- if(myTank.getX() + 60 > 0 && !isMyTankTouchWall()) {
- myTank.MoveLeft();
- }
- }
- // else if(e.getKeyCode() == KeyEvent.VK_UP){
- // opTanks.get(0).setDirect(0);
- // opTanks.get(0).MoveUp();
- // }else if(e.getKeyCode() == KeyEvent.VK_RIGHT){
- // opTanks.get(0).setDirect(1);
- // opTanks.get(0).MoveRight();
- // }else if(e.getKeyCode() == KeyEvent.VK_DOWN){
- // opTanks.get(0).setDirect(2);
- // opTanks.get(0).MoveDown();
- // }else if(e.getKeyCode() == KeyEvent.VK_LEFT) {
- // opTanks.get(0).setDirect(3);
- // opTanks.get(0).MoveLeft();
- // }
-
-
-
-
- //如果玩家按下J键,我的坦克就会发出一个炮弹
- if(e.getKeyCode() == KeyEvent.VK_J){
- // System.out.println("玩家按下了J键,开始射击!");
- // if(myTank.shot == null || myTank.shot.isLive == false) { //当坦克只能发射一颗炮弹时,先判断
- // myTank.shotOpTank();
- // }
- myTank.shotOpTank();
- }
-
- this.repaint();
-
- }
-
- @Override
- public void keyReleased(KeyEvent e) {
-
- }
-
- @Override
- public void run() {
- while(true) {
- try {
- Thread.sleep(100);
- } catch (InterruptedException e) {
- e.printStackTrace();
- }
- //判断是否击中了敌人的坦克
- for(int j=0;j<myTank.shots.size();j++) {
- if (myTank.shots.get(j) != null && myTank.shots.get(j).isLive) {
- for (int i = 0; i < opTanks.size(); i++) { //遍历敌人的所有坦克
- HitTank(myTank.shots.get(j), opTanks.get(i));
- }
- }
- }
- HitMyTank();
- this.repaint();
- }
- }
-
- //编写方法判断敌方坦克的炮弹是否打中我的坦克
- public void HitMyTank(){
- for(int i=0;i<opTanks.size();i++){
- for(int j=0;j<opTanks.get(i).shots.size();j++){
- if(myTank.isLive && opTanks.get(i).shots.get(j).isLive){
- HitTank(opTanks.get(i).shots.get(j),myTank);
- }
- }
- }
- }
-
-
- //编写方法判断炮弹是否打中坦克
- public void HitTank(Shot s,Tank opTank){
- //判断是否击中坦克
- switch (opTank.getDirect()){
- case 0: //敌人坦克向上的方向
- case 2: //敌人坦克向下的方向
- if(s.x > opTank.getX() && s.x < opTank.getX() + 50 && s.y > opTank.getY() && s.y < opTank.getY() + 60){
- s.isLive = false;
- opTank.isLive = false;
- //当坦克被击中后将坦克从集合中移除
- opTanks.remove(opTank);
- //解读,因为opTank可以是没有Tank,也可以是opTank
- if(opTank instanceof OpTank){
- Recorder.addAllOpTanksNum();
- }
- }
- break;
- case 1: //敌人坦克向右的方向
- case 3: //敌人坦克向左的方向
- if(s.x > opTank.getX() && s.x < opTank.getX() + 60 && s.y > opTank.getY() && s.y < opTank.getY() + 50){
- s.isLive = false;
- opTank.isLive = false;
- //当坦克被击中后将坦克从集合中移除
- opTanks.remove(opTank);
- //解读,因为opTank可以是没有Tank,也可以是opTank
- if(opTank instanceof OpTank){
- Recorder.addAllOpTanksNum();
- }
- }
- break;
- }
- }
-
- //判断我方坦克是否触碰到了墙壁
- public boolean isMyTankTouchWall(){
- //判断敌人当前的方向
- switch (myTank.getDirect()){
- case 0: //向上
- if(myTank.getX() > 500 && myTank.getX() < 700 && myTank.getY() > 660 && myTank.getY() < 710
- // || o.getX() > 160 && o.getX() <= 290 && o.getY() > 100 && o.getY() <= 160
- // || o.getX() > 910 && o.getX() <= 1040 && o.getY() > 100 && o.getY() <= 160
- || myTank.getX() > 550 && myTank.getX() < 650 && myTank.getY() > 160 && myTank.getY() < 260
- || myTank.getX() > 790 && myTank.getX() < 850 && myTank.getY() > 100 && myTank.getY() < 160
- || myTank.getX() > 350 && myTank.getX() < 410 && myTank.getY() > 100 && myTank.getY() < 340
- || myTank.getX() > 880 && myTank.getX() < 940 && myTank.getY() > 660 && myTank.getY() < 790
- || myTank.getX() > 260 && myTank.getX() < 320 && myTank.getY() > 660 && myTank.getY() < 790){
- return true;
- }
- //当前坦克的右上角坐标
- if(myTank.getX() + 50 > 500 && myTank.getX() + 50 < 700 && myTank.getY() > 660 && myTank.getY() < 710
- // || o.getX() + 50 >= 160 && o.getX() + 50 <= 290 && o.getY() >= 100 && o.getY() <= 160
- // || o.getX() + 50 >= 910 && o.getX() + 50 <= 1040 && o.getY() >= 100 && o.getY() <= 160
- || myTank.getX() + 50 > 550 && myTank.getX() + 50 < 650 && myTank.getY() > 160 && myTank.getY() < 260
- || myTank.getX() + 50 > 790 && myTank.getX() + 50 < 850 && myTank.getY() > 100 && myTank.getY() < 160
- || myTank.getX() + 50 > 350 && myTank.getX() + 50 < 410 && myTank.getY() > 100 && myTank.getY() < 340
- || myTank.getX() + 50 > 880 && myTank.getX() + 50 < 940 && myTank.getY() > 660 && myTank.getY() < 790
- || myTank.getX() + 50 > 260 && myTank.getX() + 50 < 320 && myTank.getY() > 660 && myTank.getY() < 790) {
- return true;
- }
- break;
- case 1: //向右
- //当前坦克的右上角坐标
- if (myTank.getX() + 60 > 500 && myTank.getX() + 60 < 700 && myTank.getY() > 660 && myTank.getY() < 710
- // || o.getX() + 60 >= 160 && o.getX() + 60 <= 290 && o.getY() >= 100 && o.getY() <= 160
- // || o.getX() + 60 >= 910 && o.getX() + 60 <= 1040 && o.getY() >= 100 && o.getY() <= 160
- || myTank.getX() + 60 > 550 && myTank.getX() + 60 < 650 && myTank.getY() > 160 && myTank.getY() < 260
- || myTank.getX() + 60 > 790 && myTank.getX() + 60 < 850 && myTank.getY() > 100 && myTank.getY() < 160
- || myTank.getX() + 60 > 350 && myTank.getX() + 60 < 410 && myTank.getY() > 100 && myTank.getY() < 340
- || myTank.getX() + 60 > 880 && myTank.getX() + 60 < 940 && myTank.getY() > 660 && myTank.getY() < 790
- || myTank.getX() + 60 > 260 && myTank.getX() + 60 < 320 && myTank.getY() > 660 && myTank.getY() < 790){
- return true;
- }
- //当前坦克的右下角坐标
- if(myTank.getX() + 60 > 500 && myTank.getX() + 60 < 700 && myTank.getY() + 50 > 660 && myTank.getY() + 50 < 710
- // || o.getX() + 60 >= 160 && o.getX() + 60 <= 290 && o.getY() + 50 >= 100 && o.getY() + 50 <= 160
- // || o.getX() + 60 >= 910 && o.getX() + 60 <= 1040 && o.getY() + 50 >= 100 && o.getY() + 50 <= 160
- || myTank.getX() + 60 > 550 && myTank.getX() + 60 < 650 && myTank.getY() + 50 > 160 && myTank.getY() + 50 < 260
- || myTank.getX() + 60 > 790 && myTank.getX() + 60 < 850 && myTank.getY() + 50 > 100 && myTank.getY() + 50 < 160
- || myTank.getX() + 60 > 350 && myTank.getX() + 60 < 410 && myTank.getY() + 50 > 100 && myTank.getY() + 50 < 340
- || myTank.getX() + 60 > 880 && myTank.getX() + 60 < 940 && myTank.getY() + 50 > 660 && myTank.getY() + 50 < 790
- || myTank.getX() + 60 > 260 && myTank.getX() + 60 < 320 && myTank.getY() + 50 > 660 && myTank.getY() + 50 < 790){
- return true;
- }
- break;
- case 2: //向下
- //当前坦克的左下角坐标
- if(myTank.getX() > 500 && myTank.getX() < 700 && myTank.getY() + 60 > 660 && myTank.getY() + 60 < 710
- // || o.getX() >= 160 && o.getX() <= 290 && o.getY() + 60 >= 100 && o.getY() + 60 <= 160
- // || o.getX() >= 910 && o.getX() <= 1040 && o.getY() + 60 >= 100 && o.getY() + 60 <= 160
- || myTank.getX() > 550 && myTank.getX() < 650 && myTank.getY() + 60 > 160 && myTank.getY() + 60 < 260
- || myTank.getX() > 790 && myTank.getX() < 850 && myTank.getY() + 60 > 100 && myTank.getY() + 60 < 160
- || myTank.getX() > 350 && myTank.getX() < 410 && myTank.getY() + 60 > 100 && myTank.getY() + 60 < 340
- || myTank.getX() > 880 && myTank.getX() < 940 && myTank.getY() + 60 > 660 && myTank.getY() + 60 < 790
- || myTank.getX() > 260 && myTank.getX() < 320 && myTank.getY() + 60 > 660 && myTank.getY() + 60 < 790){
- return true;
- }
- //当前坦克的右下角坐标
- if(myTank.getX() + 50 > 500 && myTank.getX() + 50 < 700 && myTank.getY() + 60 > 660 && myTank.getY() + 60 < 710
- // || o.getX() + 50 >= 160 && o.getX() + 50 <= 290 && o.getY() + 60 >= 100 && o.getY() + 60 <= 160
- // || o.getX() + 50 >= 910 && o.getX() + 50 <= 1040 && o.getY() + 60 >= 100 && o.getY() + 60 <= 160
- || myTank.getX() + 50 > 550 && myTank.getX() + 50 < 650 && myTank.getY() + 60 > 160 && myTank.getY() + 60 < 260
- || myTank.getX() + 50 > 790 && myTank.getX() + 50 < 850 && myTank.getY() + 60 > 100 && myTank.getY() + 60 < 160
- || myTank.getX() + 50 > 350 && myTank.getX() + 50 < 410 && myTank.getY() + 60 > 100 && myTank.getY() + 60 < 340
- || myTank.getX() + 50 > 880 && myTank.getX() + 50 < 940 && myTank.getY() + 60 > 660 && myTank.getY() + 60 < 790
- || myTank.getX() + 50 > 260 && myTank.getX() + 50 < 320 && myTank.getY() + 60 > 660 && myTank.getY() + 60 < 790){
- return true;
- }
- break;
- case 3: //向左
- //当前坦克的左上角坐标
- if(myTank.getX() > 500 && myTank.getX() < 700 && myTank.getY() > 660 && myTank.getY() < 710
- // || o.getX() >= 160 && o.getX() <= 290 && o.getY() >= 100 && o.getY() <= 160
- // || o.getX() >= 910 && o.getX() <= 1040 && o.getY() >= 100 && o.getY() <= 160
- || myTank.getX() > 550 && myTank.getX() < 650 && myTank.getY() > 160 && myTank.getY() < 260
- || myTank.getX() > 790 && myTank.getX() < 850 && myTank.getY() > 100 && myTank.getY() < 160
- || myTank.getX() > 350 && myTank.getX() < 410 && myTank.getY() > 100 && myTank.getY() < 340
- || myTank.getX() > 880 && myTank.getX() < 940 && myTank.getY() > 660 && myTank.getY() < 790
- || myTank.getX() > 260 && myTank.getX() < 320 && myTank.getY() > 660 && myTank.getY() < 790){
- return true;
- }
- //当前坦克的左下角坐标
- if(myTank.getX() > 500 && myTank.getX() < 700 && myTank.getY() + 50 > 660 && myTank.getY() + 50 < 710
- || myTank.getX() > 160 && myTank.getX() < 290 && myTank.getY() + 50 > 100 && myTank.getY() + 50 < 160
- || myTank.getX() > 910 && myTank.getX() < 1040 && myTank.getY() + 50 > 100 && myTank.getY() + 50 < 160
- || myTank.getX() > 550 && myTank.getX() < 650 && myTank.getY() + 50 > 160 && myTank.getY() + 50 < 260
- || myTank.getX() > 790 && myTank.getX() < 850 && myTank.getY() + 50 > 100 && myTank.getY() + 50 < 160
- || myTank.getX() > 350 && myTank.getX() < 410 && myTank.getY() + 50 > 100 && myTank.getY() + 50 < 340
- || myTank.getX() > 880 && myTank.getX() < 940 && myTank.getY() + 50 > 660 && myTank.getY() + 50 < 790
- || myTank.getX() > 260 && myTank.getX() < 320 && myTank.getY() + 50 > 660 && myTank.getY() + 50 < 790){
- return true;
- }
- break;
- }
- return false;
- }
-
- }

3.坦克基类(Tank)
- package com.wak.TankGame01Version;
-
- /*坦克的基类*/
- public class Tank {
- private int x; //坦克的横坐标
- private int y; //坦克的纵坐标
- private int direct = 0; //坦克的方向
- private int speed = 1; //坦克的速度
- boolean isLive = true; //坦克的存活状态
-
- public Tank(){
- this.x = 100; //默认坦克的初始x坐标为100
- this.y = 100; //默认坦克的初始y坐标为100
- }
-
- public Tank(int x,int y){ //自己设置坦克的初始x,y坐标
- this.x = x;
- this.y = y;
- }
-
-
- //设置坦克的x坐标
- public void setX(int x){
- this.x = x;
- }
-
- //设置坦克的y坐标
- public void setY(int y){
- this.y = y;
- }
-
- //获得坦克的x坐标
- public int getX(){
- return x;
- }
-
- //获得坦克的y坐标
- public int getY(){
- return y;
- }
-
- //设置坦克的方向
- public void setDirect(int direct){
- this.direct = direct;
- }
-
- //获得坦克的方向
- public int getDirect(){
- return direct;
- }
-
- //设置坦克的速度
- public void setSpeed(int speed){
- this.speed = speed;
- }
-
- //获得坦克的速度
- public int getSpeed(){
- return speed;
- }
-
- //坦克的上右下左移动
- public void MoveUp(){
- y -= speed;
- }
- public void MoveRight(){
- x += speed;
- }
- public void MoveDown(){
- y += speed;
- }
- public void MoveLeft(){
- x -= speed;
- }
- }
-
-

4.我的坦克类(MyTank)
- package com.wak.TankGame01Version;
-
- import java.util.Vector;
-
- /*自己的坦克*/
- public class MyTank extends Tank{
-
- //创建一个坦克
- private MyTank myTank = null;
-
- //定义一个shot对象,表示一个射击(线程)
- Shot shot = null;
- //创建一个存储炮弹的集合
- Vector<Shot> shots = new Vector<>();
- //设置坦克的初始化坐标
- public MyTank(int x,int y){
- this.setX(x);
- this.setY(y);
- }
-
- //射击
- public void shotOpTank(){
- //设置炮弹的初始化坐标及方向
- if(shots.size() < 5) {
- switch (this.getDirect()) {
- case 0:
- shot = new Shot(this.getX() + 25, this.getY(), 0);
- shot.speed = 4;
- break;
- case 1:
- shot = new Shot(this.getX() + 60, this.getY() + 25, 1);
- shot.speed = 4;
- break;
- case 2:
- shot = new Shot(this.getX() + 25, this.getY() + 60, 2);
- shot.speed = 4;
- break;
- case 3:
- shot = new Shot(this.getX(), this.getY() + 25, 3);
- shot.speed = 4;
- break;
- }
- //将发射的炮弹弹存入集合中
-
- shots.add(shot);
- }
- //启动我们的Shot线程
- new Thread(shot).start();
-
- }
- }

5.敌方坦克类(OpTank)
- package com.wak.TankGame01Version;
-
- import java.util.Vector;
-
- public class OpTank extends Tank implements Runnable{
- private OpTank opTank = null; //创建一个敌方坦克
- Vector<Shot> shots = new Vector<>(); //存储多个炮弹
- Vector<OpTank> opTanks = new Vector<>(); //增加成员,可以得到敌人坦克的Vector集合
- public OpTank(int x,int y){
- this.setX(x);
- this.setY(y);
- }
-
- public void setOpTanks(Vector<OpTank> opTanks){
- this.opTanks = opTanks;
- }
-
- public boolean isTouchOpTank(){ //防止坦克间重叠
- //判断当前敌人坦克的方向
- switch (this.getDirect()){
- case 0: //上
- for(int j=0;j<opTanks.size();j++){
- //取出一个敌方坦克
- OpTank o = opTanks.get(j);
- if(o != this){ //不能跟自己比
- //如果敌人是向上或者向下
- if(o.getDirect() == 0 || o.getDirect() == 2){
- //当前坦克左上角的坐标
- if(this.getX() >= o.getX()
- && this.getX() <= o.getX() + 50
- && this.getY() <= o.getY() + 60
- && this.getY() >= o.getY()){
- return true;
- }
- //当前坦克右上角的坐标
- if(this.getX() + 50 >= o.getX()
- && this.getX() + 50<= o.getX() + 50
- && this.getY() <= o.getY() + 60
- && this.getY() >= o.getY()){
- return true;
- }
- }
- //如果敌人是向右或者向左
- if(o.getDirect() == 1 || o.getDirect() == 3){
- //当前坦克左上角的坐标
- if(this.getX() >= o.getX()
- && this.getX() <= o.getX() + 60
- && this.getY() >= o.getY()
- && this.getY() <= o.getY() + 50){
- return true;
- }
- //当前坦克右上角的坐标
- if(this.getX() + 50>= o.getX()
- && this.getX() + 50<= o.getX() + 60
- && this.getY() >= o.getY()
- && this.getY() <= o.getY() + 50){
- return true;
- }
- }
- }
- }
- break;
- case 1: //右
- for(int j=0;j<opTanks.size();j++){
- //取出一辆坦克
- OpTank o = opTanks.get(j);
- if(o != this){ //不能跟自己比
- //如果敌方坦克是向上或向下
- if(o.getDirect() == 0 || o.getDirect() == 2){
- //当前坦克右上角的坐标
- if(this.getX() + 60 >= o.getX()
- && this.getX() + 60 <= o.getX() + 50
- && this.getY() >= o.getY()
- && this.getY() <= o.getY() + 60){
- return true;
- }
- //当前坦克右下角的坐标
- if(this.getX() + 60 >= o.getX()
- && this.getX() + 60 <= o.getX() + 50
- && this.getY() + 50 >= o.getY()
- && this.getY() + 50 <= o.getY() + 60){
- return true;
- }
- }
- //如果敌方坦克是向右或向左
- if(o.getDirect() == 1 || o.getDirect() == 3){
- //当前坦克右上角的坐标
- if(this.getX() + 60 >= o.getX()
- && this.getX() + 60 <= o.getX() + 60
- && this.getY() >= o.getY()
- && this.getY() <= o.getY() + 50){
- return true;
- }
- //当前坦克右下角的坐标
- if(this.getX() + 60 >= o.getX()
- && this.getX() + 60 <= o.getX() + 60
- && this.getY() + 50 >= o.getY()
- && this.getY() + 50 <= o.getY() + 50){
- return true;
- }
- }
- }
- }
- break;
- case 2: //下
- for(int j=0;j<opTanks.size();j++){
- //取出一辆坦克
- OpTank o = opTanks.get(j);
- if(o != this){ //不能跟自己比
- //如果敌方坦克是向上或向下
- if(o.getDirect() == 0 || o.getDirect() == 2){
- //当前坦克左下角的坐标
- if(this.getX() >= o.getX()
- && this.getX() <= o.getX() + 60
- && this.getY() + 60 >= o.getY()
- && this.getY() + 60 <= o.getY()){
- return true;
- }
- //当前坦克右下角的坐标
- if(this.getX() + 50>= o.getX()
- && this.getX() + 50 <= o.getX() + 60
- && this.getY() + 60 >= o.getY()
- && this.getY() + 60 <= o.getY()){
- return true;
- }
- }
- //如果敌方坦克是向右或向左
- if(o.getDirect() == 1 || o.getDirect() == 3){
- //当前坦克左下角的坐标
- if(this.getX() >= o.getX()
- && this.getX() + 60 <= o.getX() + 60
- && this.getY() >= o.getY()
- && this.getY() + 50 <= o.getY() + 50){
- return true;
- }
- //当前坦克右下角的坐标
- if(this.getX() + 50 >= o.getX()
- && this.getX() + 50 <= o.getX() + 60
- && this.getY() + 60 >= o.getY()
- && this.getY() + 60 <= o.getY() + 50){
- return true;
- }
- }
- }
- }
- break;
- case 3: //左
- for(int j=0;j<opTanks.size();j++){
- //取出一辆坦克
- OpTank o = opTanks.get(j);
- if(o != this){ //不能跟自己比
- //如果敌方坦克是向上或向下
- if(o.getDirect() == 0 || o.getDirect() == 2){
- //当前坦克左上角的坐标
- if(this.getX() >= o.getX()
- && this.getX() <= o.getX() + 60
- && this.getY() >= o.getY()
- && this.getY() <= o.getY()){
- return true;
- }
- //当前坦克左下角的坐标
- if(this.getX() >= o.getX()
- && this.getX() <= o.getX() + 60
- && this.getY() + 50 >= o.getY()
- && this.getY() + 50 <= o.getY()){
- return true;
- }
- }
- //如果敌方坦克是向右或向左
- if(o.getDirect() == 1 || o.getDirect() == 3){
- //当前坦克左上角的坐标
- if(this.getX() >= o.getX()
- && this.getX() <= o.getX() + 60
- && this.getY() >= o.getY()
- && this.getY() <= o.getY() + 50){
- return true;
- }
- //当前坦克左下角的坐标
- if(this.getX() >= o.getX()
- && this.getX() <= o.getX() + 60
- && this.getY() + 50 >= o.getY()
- && this.getY() + 50 <= o.getY() + 50){
- return true;
- }
- }
- }
- }
- break;
- }
- return false;
- }
-
-
- //判断敌方坦克是否触碰到了墙壁
- public boolean isTouchWall(){
- //判断敌人当前的方向
- switch (getDirect()){
- case 0: //向上
- for(int i=0;i<opTanks.size();i++){ //取出一个坦克
- OpTank o = opTanks.get(i);
- //当前坦克的左上角坐标
- if(o.getX() > 500 && o.getX() < 700 && o.getY() > 660 && o.getY() < 710
- // || o.getX() > 160 && o.getX() <= 290 && o.getY() > 100 && o.getY() <= 160
- // || o.getX() > 910 && o.getX() <= 1040 && o.getY() > 100 && o.getY() <= 160
- || o.getX() > 550 && o.getX() < 650 && o.getY() > 160 && o.getY() < 260
- || o.getX() > 790 && o.getX() < 850 && o.getY() > 100 && o.getY() < 160
- || o.getX() > 350 && o.getX() < 410 && o.getY() > 100 && o.getY() < 340
- || o.getX() > 880 && o.getX() < 940 && o.getY() > 660 && o.getY() < 790
- || o.getX() > 260 && o.getX() < 320 && o.getY() > 660 && o.getY() < 790){
- return true;
- }
- //当前坦克的右上角坐标
- if(o.getX() + 50 > 500 && o.getX() + 50 < 700 && o.getY() > 660 && o.getY() < 710
- // || o.getX() + 50 >= 160 && o.getX() + 50 <= 290 && o.getY() >= 100 && o.getY() <= 160
- // || o.getX() + 50 >= 910 && o.getX() + 50 <= 1040 && o.getY() >= 100 && o.getY() <= 160
- || o.getX() + 50 > 550 && o.getX() + 50 < 650 && o.getY() > 160 && o.getY() < 260
- || o.getX() + 50 > 790 && o.getX() + 50 < 850 && o.getY() > 100 && o.getY() < 160
- || o.getX() + 50 > 350 && o.getX() + 50 < 410 && o.getY() > 100 && o.getY() < 340
- || o.getX() + 50 > 880 && o.getX() + 50 < 940 && o.getY() > 660 && o.getY() < 790
- || o.getX() + 50 > 260 && o.getX() + 50 < 320 && o.getY() > 660 && o.getY() < 790){
- return true;
- }
- }
- break;
- case 1: //向右
- for(int i=0;i<opTanks.size();i++) { //取出一个坦克
- OpTank o = opTanks.get(i);
- //当前坦克的右上角坐标
- if (o.getX() + 60 > 500 && o.getX() + 60 < 700 && o.getY() > 660 && o.getY() < 710
- // || o.getX() + 60 >= 160 && o.getX() + 60 <= 290 && o.getY() >= 100 && o.getY() <= 160
- // || o.getX() + 60 >= 910 && o.getX() + 60 <= 1040 && o.getY() >= 100 && o.getY() <= 160
- || o.getX() + 60 > 550 && o.getX() + 60 < 650 && o.getY() > 160 && o.getY() < 260
- || o.getX() + 60 > 790 && o.getX() + 60 < 850 && o.getY() > 100 && o.getY() < 160
- || o.getX() + 60 > 350 && o.getX() + 60 < 410 && o.getY() > 100 && o.getY() < 340
- || o.getX() + 60 > 880 && o.getX() + 60 < 940 && o.getY() > 660 && o.getY() < 790
- || o.getX() + 60 > 260 && o.getX() + 60 < 320 && o.getY() > 660 && o.getY() < 790){
- return true;
- }
- //当前坦克的右下角坐标
- if(o.getX() + 60 > 500 && o.getX() + 60 < 700 && o.getY() + 50 > 660 && o.getY() + 50 < 710
- // || o.getX() + 60 >= 160 && o.getX() + 60 <= 290 && o.getY() + 50 >= 100 && o.getY() + 50 <= 160
- // || o.getX() + 60 >= 910 && o.getX() + 60 <= 1040 && o.getY() + 50 >= 100 && o.getY() + 50 <= 160
- || o.getX() + 60 > 550 && o.getX() + 60 < 650 && o.getY() + 50 > 160 && o.getY() + 50 < 260
- || o.getX() + 60 > 790 && o.getX() + 60 < 850 && o.getY() + 50 > 100 && o.getY() + 50 < 160
- || o.getX() + 60 > 350 && o.getX() + 60 < 410 && o.getY() + 50 > 100 && o.getY() + 50 < 340
- || o.getX() + 60 > 880 && o.getX() + 60 < 940 && o.getY() + 50 > 660 && o.getY() + 50 < 790
- || o.getX() + 60 > 260 && o.getX() + 60 < 320 && o.getY() + 50 > 660 && o.getY() + 50 < 790){
- return true;
- }
- }
- break;
- case 2: //向下
- for(int i=0;i<opTanks.size();i++) { //取出一个坦克
- OpTank o = opTanks.get(i);
- //当前坦克的左下角坐标
- if(o.getX() > 500 && o.getX() < 700 && o.getY() + 60 > 660 && o.getY() + 60 < 710
- // || o.getX() >= 160 && o.getX() <= 290 && o.getY() + 60 >= 100 && o.getY() + 60 <= 160
- // || o.getX() >= 910 && o.getX() <= 1040 && o.getY() + 60 >= 100 && o.getY() + 60 <= 160
- || o.getX() > 550 && o.getX() < 650 && o.getY() + 60 > 160 && o.getY() + 60 < 260
- || o.getX() > 790 && o.getX() < 850 && o.getY() + 60 > 100 && o.getY() + 60 < 160
- || o.getX() > 350 && o.getX() < 410 && o.getY() + 60 > 100 && o.getY() + 60 < 340
- || o.getX() > 880 && o.getX() < 940 && o.getY() + 60 > 660 && o.getY() + 60 < 790
- || o.getX() > 260 && o.getX() < 320 && o.getY() + 60 > 660 && o.getY() + 60 < 790){
- return true;
- }
- //当前坦克的右下角坐标
- if(o.getX() + 50 > 500 && o.getX() + 50 < 700 && o.getY() + 60 > 660 && o.getY() + 60 < 710
- // || o.getX() + 50 >= 160 && o.getX() + 50 <= 290 && o.getY() + 60 >= 100 && o.getY() + 60 <= 160
- // || o.getX() + 50 >= 910 && o.getX() + 50 <= 1040 && o.getY() + 60 >= 100 && o.getY() + 60 <= 160
- || o.getX() + 50 > 550 && o.getX() + 50 < 650 && o.getY() + 60 > 160 && o.getY() + 60 < 260
- || o.getX() + 50 > 790 && o.getX() + 50 < 850 && o.getY() + 60 > 100 && o.getY() + 60 < 160
- || o.getX() + 50 > 350 && o.getX() + 50 < 410 && o.getY() + 60 > 100 && o.getY() + 60 < 340
- || o.getX() + 50 > 880 && o.getX() + 50 < 940 && o.getY() + 60 > 660 && o.getY() + 60 < 790
- || o.getX() + 50 > 260 && o.getX() + 50 < 320 && o.getY() + 60 > 660 && o.getY() + 60 < 790){
- return true;
- }
- }
- break;
- case 3: //向左
- for(int i=0;i<opTanks.size();i++) { //取出一个坦克
- OpTank o = opTanks.get(i);
- //当前坦克的左上角坐标
- if(o.getX() > 500 && o.getX() < 700 && o.getY() > 660 && o.getY() < 710
- // || o.getX() >= 160 && o.getX() <= 290 && o.getY() >= 100 && o.getY() <= 160
- // || o.getX() >= 910 && o.getX() <= 1040 && o.getY() >= 100 && o.getY() <= 160
- || o.getX() > 550 && o.getX() < 650 && o.getY() > 160 && o.getY() < 260
- || o.getX() > 790 && o.getX() < 850 && o.getY() > 100 && o.getY() < 160
- || o.getX() > 350 && o.getX() < 410 && o.getY() > 100 && o.getY() < 340
- || o.getX() > 880 && o.getX() < 940 && o.getY() > 660 && o.getY() < 790
- || o.getX() > 260 && o.getX() < 320 && o.getY() > 660 && o.getY() < 790){
- return true;
- }
- //当前坦克的左下角坐标
- if(o.getX() > 500 && o.getX() < 700 && o.getY() + 50 > 660 && o.getY() + 50 < 710
- || o.getX() > 160 && o.getX() < 290 && o.getY() + 50 > 100 && o.getY() + 50 < 160
- || o.getX() > 910 && o.getX() < 1040 && o.getY() + 50 > 100 && o.getY() + 50 < 160
- || o.getX() > 550 && o.getX() < 650 && o.getY() + 50 > 160 && o.getY() + 50 < 260
- || o.getX() > 790 && o.getX() < 850 && o.getY() + 50 > 100 && o.getY() + 50 < 160
- || o.getX() > 350 && o.getX() < 410 && o.getY() + 50 > 100 && o.getY() + 50 < 340
- || o.getX() > 880 && o.getX() < 940 && o.getY() + 50 > 660 && o.getY() + 50 < 790
- || o.getX() > 260 && o.getX() < 320 && o.getY() + 50 > 660 && o.getY() + 50 < 790){
- return true;
- }
- }
- break;
- }
- return false;
- }
-
-
- @Override
- public void run() {
- while(true){
-
- //这里判断坦克的方向,创建对应的炮弹
- if(isLive && shots.size() < 6){
- Shot s = null;
- switch (getDirect()){
- case 0:
- s = new Shot(getX() + 25,getY(),0);
- break;
- case 1:
- s = new Shot(getX() + 60,getY() + 25,1);
- break;
- case 2:
- s = new Shot(getX() + 25,getY() + 60,2);
- break;
- case 3:
- s = new Shot(getX(),getY() + 25,3);
- break;
- }
-
- //每隔2秒发射一个炮弹
- try {
- Thread.sleep(2000);
- } catch (InterruptedException e) {
- e.printStackTrace();
- }
-
- shots.add(s);
-
- new Thread(s).start();
- }
-
- //坦克移动的方向
- switch (this.getDirect()){
- case 0:
- for(int i=0;i<60;i++) {
- if (getY() > 0 && !isTouchOpTank() && !isTouchWall()){
- MoveUp();
- }
- //休眠
- try {
- Thread.sleep(50);
- } catch (InterruptedException e) {
- e.printStackTrace();
- }
- }
- break;
- case 1:
- for (int i=0;i<60;i++){
- if(getX() + 60< 1200 && !isTouchOpTank() && !isTouchWall()) {
- MoveRight();
- }
- //休眠
- try {
- Thread.sleep(50);
- } catch (InterruptedException e) {
- e.printStackTrace();
- }
- }
- break;
- case 2:
- for (int i=0;i<60;i++){
- if(getY() + 60 < 900 && !isTouchOpTank() && !isTouchWall()) {
- MoveDown();
- }
- //休眠
- try {
- Thread.sleep(50);
- } catch (InterruptedException e) {
- e.printStackTrace();
- }
- }
- break;
- case 3:
- for (int i=0;i<60;i++){
- if(getX() > 0 && !isTouchOpTank() && !isTouchWall()) {
- MoveLeft();
- }
- //休眠
- try {
- Thread.sleep(50);
- } catch (InterruptedException e) {
- e.printStackTrace();
- }
- }
- break;
- }
- setDirect((int)(Math.random() * 4));
- // System.out.println("坦克的x坐标" + getX() + " y坐标 "+ getY() );
- if(!isLive){
- break;
- }
- }
- }
- }

6.炮弹类(Shot)
- package com.wak.TankGame01Version;
-
- public class Shot implements Runnable{
- int x; //子弹的x坐标
- int y; //子弹的y坐标
- int direct = 0; //子弹的方向
- int speed = 4; //子弹的速度
- boolean isLive = true; //子弹的存活状态
-
- public Shot(int x,int y,int direct){
- this.x = x;
- this.y = y;
- this.direct = direct;
- }
-
- public void setShotSpeed(int speed){
- this.speed = speed;
- }
-
- @Override
- public void run() { //射击
- while(isLive){
- //休眠
- try {
- Thread.sleep(50);
- } catch (InterruptedException 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;
- }
-
- // System.out.println("炮弹的x坐标:" + x + ",炮弹的y坐标:" + y);
- //如果炮弹弹撞到墙壁,则销毁
- //当炮弹碰到敌人坦克时,也应当结束
- if(!(x > 0 && x < 1200 && y > 0 && y <= 900 && isLive)
- // || x >= 160 && x <= 290 && y >= 100 && y <= 160
- // || x >= 910 && x<= 1040 && y >= 100 && y <= 160
- || x > 550 && x < 650 && y > 160 && y < 260
- || x > 790 && x < 850 && y > 100 && y < 340
- || x > 350 && x < 410 && y > 100 && y < 340
- || x > 880 && x < 940 && y > 660 && y < 790
- || x > 260 && x < 320 && y > 660 && y < 790
- || x > 500 && x < 700 && y > 660 && y < 710){
- isLive = false;
- // System.out.println("炮弹已销毁");
- }
- }
- }
- }

7.记录信息类(Recorder)
- package com.wak.TankGame01Version;
-
- import java.awt.*;
- import java.io.*;
- import java.util.Vector;
-
- public class Recorder {
- private static int allOpTanksNum = 0;
- //定义IO对象,准备写数据到文件中
- private static FileWriter fw = null;
- private static BufferedWriter bw = null;
- private static BufferedReader br = null;
- private static String recordFile = "D:\\myTankGameRecord.txt";
- //定义Vec,指向GamePanel对象的 敌人坦克Vector
- private static Vector<OpTank> opTanks = null;
- //定义一个Node 的Vector,用于保存敌人的信息node
- private static Vector<Node> nodes = new Vector<>();
-
- public static void setOpTanks(Vector<OpTank> opTanks){
- Recorder.opTanks = opTanks;
- }
-
- public static int getAllOpTanksNum(){
- return allOpTanksNum;
- }
-
- public static void setAllOpTanksNum(int allOpTanksNum){
- Recorder.allOpTanksNum = allOpTanksNum;
- }
-
-
- //当我方坦克击毁一个敌人坦克,就应当allOpTanksNum++
- public static void addAllOpTanksNum(){
- Recorder.allOpTanksNum++;
- }
-
- //增加一个方法,当游戏退出时,我们将allOpTanksNum保存到recordFile
- //对KeepRecord方法进行升级,保存敌人坦克的坐标和方向
- public static void KeepRecord(){
- try {
- bw = new BufferedWriter((new FileWriter((recordFile))));
- bw.write(allOpTanksNum + "\r\n");
- //遍历敌人坦克的Vector,然后根据情况保存即可
- for(int i=0;i<opTanks.size();i++){
- //取出敌人坦克
- OpTank o = opTanks.get(i);
- if(o.isLive){
- //保存该opTank的信息
- String record = o.getX() + " " + o.getY() + " " + o.getDirect();
- //写入到文件
- bw.write(record + "\r\n");
- }
- }
- } catch (IOException e) {
- e.printStackTrace();
- }finally {
- if (bw != null) {
- try {
- bw.close();
- } catch (IOException e) {
- e.printStackTrace();
- }
- }
- }
- }
-
- // //增加一个方法,用于读取recordFile,恢复相关信息
- // public static Vector<Node> getNodesAndEnemyTankRec(){
- // try {
- // br = new BufferedReader(new FileReader(recordFile));
- //
- // } catch (FileNotFoundException e) {
- // e.printStackTrace();
- // }finally {
- //
- // }
- // return null;
- // }
- }

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