Java实现经典坦克大战及源代码下载

Java实现经典坦克大战及源代码下载一 简单介绍这是一个功能相对全的 JAVA 版坦克大战 界面绘制是通过 JAVA 的图形化用户界面完成的 包括了菜单界面和游戏界面 其中菜单界面可以供玩家选择重新开始游戏 暂停 继续 是否播放背景音乐 帮助等操作 游戏界面绘制了坦克 河流 草地 鹰碉堡等经典坦克场景 玩家在游戏界面操作坦克开始对战 本游戏使用的主要技术有 Swing 编程 面向对象编程 多线程编程 本

目录

一、简单介绍

二、工程目录

三、具体代码

四、运行效果截图

五、总结

六、说明与下载


一、简单介绍

        这是一个功能相对全的Java版坦克大战,界面绘制是通过Java的图形化用户界面swing完成的,包括了菜单界面和游戏界面。其中菜单界面可以供玩家选择重新开始游戏、暂停、继续、是否播放背景音乐、设置游戏难度等操作;游戏界面绘制了坦克、河流、草地、墙壁、鹰碉堡等经典坦克场景,玩家在游戏界面操作自己的坦克开始对战。

         本游戏使用的主要技术有Swing编程、面向对象编程、多线程编程。本想用I/O编程实现保存游戏数据,感觉单机版的没必要就没弄了。

游戏实现的主要功能有:

1、我方坦克默认可以渡河,碰到墙壁不能走,鹰碉堡被击中游戏结束

2、坦克可以上下左右、以及左上左下右上右下八个方向移动,移动时添加音效

3、坦克可以发子弹(可以连发),发射时添加音效

4、击中对方坦克时,坦克消失,显示爆炸效果;子弹击中墙壁时,子弹消失

5、我方坦克吃到血块时,生命值加30(可以自己设定);我方被击中时每次血量减50

6、移动过程中检测碰撞,包括坦克与坦克,坦克与草地、河流、墙壁等

7、声音处理(开始音乐、背景音乐、移动音效、爆炸音效等)

8、菜单处理(重新开始、暂停/继续游戏、是否播放背景音乐、设置游戏难度、帮助等)

9、默认击中一个敌人得100分,达到1500分进入下一关,一共设置了3关

10、生命数,默认两条命,命数用完游戏结束

二、工程目录

 Java实现经典坦克大战及源代码下载

images文件夹存放草、鹰碉堡和河流图片,墙壁是用画笔画的;audio存放所有音效文件;所有java代码都存放在com.chuenhung.tank包下面。

三、具体代码

由于篇幅有限,这里只贴出Tank类源代码。Tank类是公用的,通过good变量来区分我方和敌人坦克。

Tank类源代码:

package com.chuenhung.tank; import java.awt.Color; import java.awt.Graphics; import java.awt.Rectangle; import java.awt.event.KeyEvent; import java.util.List; import java.util.Random; / * *@Description 坦克类,包括坦克移动、坦克发射炮弹等 *@author Chuenhung *@email @.com *@date 2017年1月4日 */ public class Tank { // 坦克X方向速度,设置游戏难度时可拓展 public static int XSPEED = 5; // 坦克Y方向速度,设置游戏难度时可拓展 public static int YSPEED = 5; // 坦克宽度 public static final int WIDTH = 30; // 坦克高度 public static final int HEIGHT = 30; // 坦克是否活着 private boolean live = true; // 坦克的生命值 private int life = 100; // 持有对TankClient大管家的引用 TankClient tc; // 判断是否是我方坦克,默认true private boolean good=true; // 用于记录坦克原来的坐标,碰到墙、坦克时方便退一步 private int oldX,oldY; // 绘制坦克的左上角坐标 private int x, y; // 用于产生随机数 private static Random r = new Random(); // 用于控制敌人随机发出子弹 private int step = r.nextInt(30)+10; // 判断是否按下方向键 private boolean bL=false, bU=false, bR=false, bD = false; // 枚举类型定义了坦克的八个方向,和静止时的方向 enum Direction {L, LU, U, RU, R, RD, D, LD, STOP}; // 坦克的方向 private Direction dir = Direction.STOP; // 炮筒的方向 private Direction ptDir = Direction.D; // 血条 private BloodBar bar = new BloodBar(); // 剩余生命数 private int remainLives =2; // 构造方法 public Tank(int x, int y, boolean good) { this.x = x; this.y = y; this.good = good; } // 构造方法 public Tank(int x, int y, boolean good, Direction dir,TankClient tc) { this(x, y, good); this.tc = tc; this.oldX=x; this.oldY=y; this.dir=dir; } / * * @Description 画出坦克 * @param g */ public void draw(Graphics g) { if(!live) { if(!good) { tc.tanks.remove(this); } return; } Color c = g.getColor(); if(good) g.setColor(Color.RED); else g.setColor(Color.BLUE); g.fillOval(x, y, WIDTH, HEIGHT); g.setColor(c); //血条 if(good) bar.draw(g); switch(ptDir) { case L: g.drawLine(x + Tank.WIDTH/2, y + Tank.HEIGHT/2, x, y + Tank.HEIGHT/2); break; case LU: g.drawLine(x + Tank.WIDTH/2, y + Tank.HEIGHT/2, x, y); break; case U: g.drawLine(x + Tank.WIDTH/2, y + Tank.HEIGHT/2, x + Tank.WIDTH/2, y); break; case RU: g.drawLine(x + Tank.WIDTH/2, y + Tank.HEIGHT/2, x + Tank.WIDTH, y); break; case R: g.drawLine(x + Tank.WIDTH/2, y + Tank.HEIGHT/2, x + Tank.WIDTH, y + Tank.HEIGHT/2); break; case RD: g.drawLine(x + Tank.WIDTH/2, y + Tank.HEIGHT/2, x + Tank.WIDTH, y + Tank.HEIGHT); break; case D: g.drawLine(x + Tank.WIDTH/2, y + Tank.HEIGHT/2, x + Tank.WIDTH/2, y + Tank.HEIGHT); break; case LD: g.drawLine(x + Tank.WIDTH/2, y + Tank.HEIGHT/2, x, y + Tank.HEIGHT); break; } move(); } /* * 坦克移动 */ void move() { this.oldX=x; this.oldY=y; switch(dir) { case L: x -= XSPEED; break; case LU: x -= XSPEED; y -= YSPEED; break; case U: y -= YSPEED; break; case RU: x += XSPEED; y -= YSPEED; break; case R: x += XSPEED; break; case RD: x += XSPEED; y += YSPEED; break; case D: y += YSPEED; break; case LD: x -= XSPEED; y += YSPEED; break; case STOP: break; } if(this.dir != Direction.STOP) { this.ptDir = this.dir; } if(!good){ Direction[] dirs = Direction.values(); if(step==0){ step=r.nextInt(30)+10; int rn = r.nextInt(9); this.dir=dirs[rn]; } step--; //敌人发子弹 if(r.nextInt(40)>36){ this.fire(); } } if(x < 0) x = 0; if(y < 55) y = 55; if(x + Tank.WIDTH > TankClient.GAME_WIDTH) x = TankClient.GAME_WIDTH - Tank.WIDTH; if(y + Tank.HEIGHT > TankClient.GAME_HEIGHT) y = TankClient.GAME_HEIGHT - Tank.HEIGHT; } / * *@Description 用于撞到墙、坦克时返回上一步 */ private void stay(){ x=oldX; y=oldY; } / * *@Description 按下键时监听 * @param e */ public void keyPressed(KeyEvent e) { int key = e.getKeyCode(); switch(key) { case KeyEvent.VK_R: tc.bloods.clear(); tc.grasses.clear(); tc.rivers.clear(); tc.walls.clear(); tc.missiles.clear(); tc.tanks.clear(); tc.explodes.clear(); //关卡、分数重置 tc.score=0; tc.level=1; //草地 tc.newGrass(); //河流 tc.newRiver(); //墙 tc.newWall(); //当在区域中没有坦克时,就出来坦克 if (tc.tanks.size() == 0) { tc.newTank(); } tc.myTank = new Tank(220, 560, true, Direction.STOP, tc);//设置自己出现的位置 if(!tc.home.isLive()){ tc.home.setLive(true); } tc.dispose(); new TankClient().lauchFrame(); break; case KeyEvent.VK_LEFT : bL = true; break; case KeyEvent.VK_UP : bU = true; break; case KeyEvent.VK_RIGHT : bR = true; break; case KeyEvent.VK_DOWN : bD = true; break; } locateDirection(); } / * *@Description 定位坦克的方向 */ void locateDirection() { if(bL && !bU && !bR && !bD) dir = Direction.L; else if(bL && bU && !bR && !bD) dir = Direction.LU; else if(!bL && bU && !bR && !bD) dir = Direction.U; else if(!bL && bU && bR && !bD) dir = Direction.RU; else if(!bL && !bU && bR && !bD) dir = Direction.R; else if(!bL && !bU && bR && bD) dir = Direction.RD; else if(!bL && !bU && !bR && bD) dir = Direction.D; else if(bL && !bU && !bR && bD) dir = Direction.LD; else if(!bL && !bU && !bR && !bD) dir = Direction.STOP; } / * * @Description 松开键时监听 * @param e */ public void keyReleased(KeyEvent e) { int key = e.getKeyCode(); switch(key) { case KeyEvent.VK_J: superFire(); break; case KeyEvent.VK_SPACE: fire(); //发射炮弹音效 new Audio(2); break; case KeyEvent.VK_LEFT : bL = false; new Audio(1); break; case KeyEvent.VK_UP : bU = false; new Audio(1); break; case KeyEvent.VK_RIGHT : bR = false; new Audio(1); break; case KeyEvent.VK_DOWN : bD = false; new Audio(1); break; } locateDirection(); } / * * @Description 坦克开火 * @return 炮弹对象 */ public Missile fire() { if(!live)return null; int x = this.x + Tank.WIDTH/2 - Missile.WIDTH/2; int y = this.y + Tank.HEIGHT/2 - Missile.HEIGHT/2; Missile m = new Missile(x, y, ptDir,this.good, this.tc); tc.missiles.add(m); return m; } / * * @Description 坦克根据方向开火 * @return 炮弹对象 */ public Missile fire(Direction dir) { if(!live)return null; int x = this.x + Tank.WIDTH/2 - Missile.WIDTH/2; int y = this.y + Tank.HEIGHT/2 - Missile.HEIGHT/2; Missile m = new Missile(x, y, dir,this.good, this.tc); tc.missiles.add(m); return m; } / * * @Description 超级炮弹,可以向八个方向开火 */ public void superFire(){ Direction[] dirs = Direction.values(); for(int i=0;i<8;i++){ fire(dirs[i]); } } / * * @Description 判断坦克是否撞墙 * @param w 墙对象 * @return 是否撞墙了 */ public boolean CollidesWithWall(Wall w){ if(this.live&&this.getRect().intersects(w.getRect())){ this.stay(); return true; } return false; } public boolean CollidesWithWalls(List 
   
     walls){ for(int i=0;i 
    
      tanks){ for(int i=0;i 
     
       rivers){ for(int i=0;i 
       
      
     
   

四、运行效果截图

重新开始、暂停、继续、发射子弹、爆炸效果演示:

Java实现经典坦克大战及源代码下载

渡河、吃血块功能演示:

Java实现经典坦克大战及源代码下载

 




五、总结

源代码参考了马老师的Java坦克大战视频教程以及众多互联网资源,这次练手有利于深入理解Java面向对象编程、Swing界面编程以及多线程编程

大部分功能是本人在实训期间完成(2016.12.30),当时有兴趣想巩固一下Java知识就开始做了
这个坦克大战到这里就告一个段落,时间荏苒,马上就要毕业了,要学的东西很多的,希望以后能够做出更加优秀的作品。
该程序谨供参考,不得用于商业用途,希望大神能提出更多优化的建议,一起交流。
若有关内容侵犯了您的权益请及时联系作者删除,作者邮箱@.com






更新于2021/06/04

六、说明与下载

下载地址

备用下载地址

版权声明:本文内容由互联网用户自发贡献,该文观点仅代表作者本人。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如发现本站有涉嫌侵权/违法违规的内容, 请联系我们举报,一经查实,本站将立刻删除。

发布者:全栈程序员-站长,转载请注明出处:https://javaforall.net/200616.html原文链接:https://javaforall.net

(0)
上一篇 2026年3月20日 上午10:25
下一篇 2026年3月20日 上午10:26


相关推荐

  • instanceof的用法

    instanceof的用法instanceof 运算符返回一个布尔值 表示对象是否为某个构造函数的实例 如下 functionPers this name wang varp1 newPerson console log p1instanceof trueinstance 运算符的左边是实例对象 右边是构造函数 它会检查右边构造函数的原型对象 prototype 是否在左边对象的原型链上 因此 下面这种写法是等价的 console log Perso

    2026年3月18日
    2
  • c++用socket,ftp进行文件传输,实现上传与下载文件功能

    c++用socket,ftp进行文件传输,实现上传与下载文件功能

    2021年3月12日
    233
  • 什么是纯函数?

    什么是纯函数?纯函数的概念 一个函数的返回结果只依赖其参数 并且执行过程中没有副作用 下面我们来分别说明一下概念中的两个条件 返回结果只依赖其参数返回值只和函数参数有关 与外部无关 无论外部发生什么样的变化 函数的返回值都不会改变 非纯函数返回值与 a 相关 无法预料 consta 1constfoo b gt a bfoo 2

    2026年3月16日
    2
  • MidJourney部署教程

    MidJourney部署教程

    2026年3月15日
    2
  • vue 全局变量

    vue 全局变量1 示例代码 include iostream usingnamespa intfunction inta intb 2 c 0 a b c 仅在函数 function 内有效 returna b c intmain intm n m n 仅在函数 main 内有效 cin gt gt m n function m cout lt iostream

    2026年3月19日
    2
  • Flutter动态化框架Thresh

    Flutter动态化框架Thresh原文链接 满帮动态化 Flutter 框架 Thresh 现在开源了一 前言移动端技术栈自诞生以来 其双端开发成本和发布效率一直广受诟病 为了解决这些问题 前端跨端技术一直在不断尝试 希望能一次开发 多端运行并且能做到快速发布 期间经历了多个技术发展阶段 第一阶段 以 H5 为代表 基于 webview 渲染只需一次开发即可运行在双端 解决了开发效率低下的问题 但是 webview 存在严重的性能问题 用户的交互体验相比 Native 渲染有明显差距 第二阶段 以 RN 和 Weex 为代表 前端技术栈开发 Native 渲

    2026年3月16日
    3

发表回复

您的邮箱地址不会被公开。 必填项已用 * 标注

关注全栈程序员社区公众号