原创性声明

此博文的出处 为 http://blog.csdn.net/zhujunxxxxx/article/details/40460931如果进行转载请注明出处。本文作者原创,邮箱zhujunxxxxx@163.com,如有问题请联系作者

前言

很久没碰java了,今天突然找出了大二时期写的一个坦克大战游戏的源码,然后运行了一下,竟然依然如此的亲切,突然想到了以前大二的时候的点点时光。好了不废话了,先给出一张图。
这个就是整个游戏的界面了,界面全是用的java画的,不是很好看。如果想要好看的得做成图片版本的

原理

游戏的基本原理就是,一开始创建N个敌人的实例,多线程在界面中移动(移动使用的是重写paint函数来实现的),然后随机移动和发射子弹。
还有就是使用了简单的碰撞检测方法来实现子弹击中别人和碰到障碍物
双缓冲技术,消除频闪

坦克类

坦克类是这个游戏的主要对象,可以分为三种坦克 一种是自己的坦克,一种是普通坦克,而另一种是BOSS坦克(血多 伤害大),不过都是一个类来实现的
import java.awt.*;
import java.awt.event.*;
import java.util.*;
public class Tank {public static final int XSPEED = 5;public static final int YSPEED = 5;public static final int WIDTH = 30;public static final int HEIGHT = 30;TankClient tc;private int x, y;//坦克的坐标,即位置private int oldX, oldY;//用来保存上一步的坐标,撞墙的时候调整方向用的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 int step = r.nextInt(12) + 3;private boolean isSuper=false;public boolean isSuper(){return isSuper;}public void setSuper(boolean isSuper){this.isSuper = isSuper;}private static Random r = new Random();//随机数产生器private boolean good;//区分好坏的变量private boolean boss;public boolean isBoss(){return boss;}public boolean isGood(){return good;}public void setGood(boolean good){this.good = good;}private BloodBar bb=new BloodBar();//血条//坦克生命值的变量private int life=100; public int getLife(){return life;}public void setLife(int life){this.life = life;}//坦克生死的变量private boolean live=true;public boolean isLive(){return live;}public void setLive(boolean live){this.live = live;}//坦克的构造方法public Tank(int x, int y,boolean good) {this.x = x;this.y = y;this.oldX = x;this.oldY = y;this.good=good;}public Tank(int x, int y,boolean good,Direction dir, TankClient tc) {this(x, y,good);this.dir=dir;this.tc = tc;}public Tank(int x, int y,boolean good,boolean boss, Direction dir, TankClient tc) {this(x, y,good);this.dir=dir;this.boss=boss;this.tc = tc;}//画坦克的方法public void draw(Graphics g) {if(!live) return;//Tank死了就不在重画了Color c = g.getColor();if(good)//通过好坏设置颜色{g.setColor(Color.CYAN);}else if(boss){g.setColor(Color.RED);}    else {g.setColor(Color.BLUE);}g.fillOval(x, y, WIDTH, HEIGHT);g.setColor(c);if(good) bb.draw(g);//我方坦克有血条if(boss) bb.draw(g);//boss有血条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(x < 0) x = 0;if(y < 30) y = 30;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;//坏蛋坦克的随机移动,以及发子弹的时间if(!good&&!boss) {Direction[] dirs = Direction.values();if(step == 0) {step = r.nextInt(12) + 3;int rn = r.nextInt(dirs.length);dir = dirs[rn];}          step --;            if(r.nextInt(40) > 38) this.fire();}//boss坦克的攻击方法if(!good&&boss){Direction[] dirs = Direction.values();if(step == 0) {step = r.nextInt(12) + 3;int rn = r.nextInt(dirs.length);dir = dirs[rn];}   step --;if(r.nextInt(40) > 20)this.fire();}}//按下键时进行设置键位标志,用于方向定位判断public void keyPressed(KeyEvent e) {int key = e.getKeyCode();switch(key) {case KeyEvent.VK_CAPS_LOCK:this.setSuper(!this.isSuper());case KeyEvent.VK_F2 :if(!this.live) {this.live = true;this.life = 100;}case KeyEvent.VK_CONTROL:fire();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();//每次按键后就判断方向}//Tank的方向定位,通过按键后设置的标志进行判断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;}//方向键抬起来时的,恢复键位标志,也进行方向判断public void keyReleased(KeyEvent e) {int key = e.getKeyCode();switch(key) {case KeyEvent.VK_LEFT :bL = false;break;case KeyEvent.VK_UP :bU = false;break;case KeyEvent.VK_RIGHT :bR = false;break;case KeyEvent.VK_DOWN :bD = false;break;case KeyEvent.VK_A :superFire();break;}locateDirection();        }//发出一发子弹的方法,向missiles里面添加子弹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;if(good&&this.isSuper())//判断是不是超级炮弹{m = new Missile(x, y,good, ptDir,this.tc,true);}else {m = new Missile(x, y,good, ptDir,this.tc);}tc.missiles.add(m);return m;}//SuperFire向每个方向发子弹的方法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,good, Dir,this.tc);tc.missiles.add(m);return m;}private void superFire(){Direction[] dirs = Direction.values();for(int i=0;i<8;i++){//tc.missiles.add(fire(dirs[i]));fire(dirs[i]);}}//判断相撞的方法所需的public Rectangle getRect() {return new Rectangle(x, y, WIDTH, HEIGHT);}//与坦克和墙相撞时停下来的方法private void stay() {x = oldX;y = oldY;}//判断坦克是否与墙相撞的方法public boolean collidesWithWall(Wall w) {if(this.live && this.getRect().intersects(w.getRect())) {this.stay();return true;}return false;}//判断坦克是否与坦克相撞的方法public boolean collidesWithTanks(java.util.List<Tank> tanks) {for(int i=0; i<tanks.size(); i++) {Tank t = tanks.get(i);if(this != t) {if(this.live && t.isLive() && this.getRect().intersects(t.getRect())) {this.stay();t.stay();return true;}}}return false;}//血条的内部类private class BloodBar {public void draw(Graphics g) {Color c = g.getColor();g.setColor(Color.orange);g.drawRect(x, y-10, WIDTH, 10);int w = WIDTH * life/100 ;g.fillRect(x, y-10, w, 10);g.setColor(c);}}//吃血块的方法public boolean eat(Blood b) {if(this.live && b.isLive() && this.getRect().intersects(b.getRect())) {this.life = 100;b.setLive(false);return true;}return false;}}

坦克类内部有很多的操作方法,还有一个血条。

子弹类

子弹类就是分为敌方子弹和我方子弹,具有移动速度等属性,具有碰撞检测等功能。
import java.awt.*;
import java.util.List;
public class Missile {public static final int XSPEED = 10;//子弹速度的变量public static final int YSPEED = 10;public static  int WIDTH = 10;//子弹大小public static  int HEIGHT = 10;int x, y;private TankClient tc;Tank.Direction dir;//方向变量private boolean isSuper;private boolean live = true;//子弹的生死变量public boolean isLive() {return live;}private boolean good;//坦克的好坏之分变量public boolean isGood(){return good;}//Missile的两个构造方法public Missile(int x, int y, Tank.Direction dir) {this.x = x;this.y = y;this.dir = dir;}public Missile(int x, int y,boolean good, Tank.Direction dir, TankClient tc) {this(x, y, dir);this.tc = tc;this.good=good;}public Missile(int x, int y,boolean good, Tank.Direction dir, TankClient tc,boolean isSuper) {this(x, y, dir);this.tc = tc;this.isSuper=isSuper;this.good=good;}//画子弹的方法public void draw(Graphics g) {if(!live) {tc.missiles.remove(this);return;}Color c = g.getColor();if(good&&isSuper)//是超级炮弹就变大{g.setColor(Color.YELLOW);g.fillOval(x-5, y-5, 20, 20);}else if(good&&!isSuper) {g.setColor(Color.YELLOW);g.fillOval(x, y, WIDTH, HEIGHT);}else {g.setColor(Color.RED);g.fillOval(x, y, WIDTH, HEIGHT);}g.setColor(c);move();//画子弹的时候就要移动}//子弹的移动方法,与坦克方位有关private void move() {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(x < 0 || y < 0 || x > TankClient.GAME_WIDTH || y > TankClient.GAME_HEIGHT) {live = false;tc.missiles.remove(this);}}public Rectangle getRect() {return new Rectangle(x, y, WIDTH, HEIGHT);}//子弹与子弹相撞的方法,且子弹分好坏public boolean hitMissile(Missile m) {if(this.live && this.getRect().intersects(m.getRect()) && m.isLive() && this.good !=m.isGood() ){this.live=false;m.live=false;return true;}return false;}public boolean hitMissiles(List<Missile> missiles) {for(int i=0; i<missiles.size(); i++) {if(hitMissile(missiles.get(i))) {//调用了hitMissile方法missiles.remove(missiles.get(i));return true;}}return false;}public boolean hitTank(Tank t) {if(this.live && this.getRect().intersects(t.getRect()) && t.isLive() && this.good !=t.isGood() ){if(t.isGood())//自己被击中减血{t.setLife(t.getLife()-20);if(t.getLife()<=0)t.setLive(false);}else if(t.isBoss())//BOSS被击中{if(this.isSuper)//被超级炮弹击中{t.setLife(t.getLife()-33);if(t.getLife()<=0)t.setLive(false);}else {       t.setLife(t.getLife()-5);if(t.getLife()<=0)t.setLive(false);}}else//坏人直接死t.setLive(false);      //t.setLive(false);this.live = false;Explode e = new Explode(x, y, tc);tc.explodes.add(e);return true;}return false;}//子弹与坦克相撞,且子弹分好坏(打敌人坦克的方法)public boolean hitTanks(List<Tank> tanks) {for(int i=0; i<tanks.size(); i++) {if(hitTank(tanks.get(i))) {//调用了hitTank方法tanks.remove(tanks.get(i));return true;}}return false;}//子弹与墙相撞的方法public boolean hitWall(Wall w) {if(this.live && this.getRect().intersects(w.getRect())) {this.live = false;return true;}return false;}
}

主程序类

主类主要是实现显示界面的功能,把在内存中的对象画出来,实现动画的效果。
import java.awt.*;
import java.awt.event.*;
import java.util.List;
import java.util.ArrayList;
import org.omg.CORBA.PUBLIC_MEMBER;
public class TankClient extends Frame{public static  int GAME_WIDTH = 800;public static int GAME_HEIGHT = 600;Tank myTank = new Tank(200, 300,true,Tank.Direction.STOP, this);Tank BossTank = new Tank(60, 50,false,true,Tank.Direction.D,this);List<Missile> missiles=new ArrayList<Missile>();//装子弹的容器List<Explode> explodes = new ArrayList<Explode>();//装爆炸的容器List<Tank> tanks = new ArrayList<Tank>();//装敌方坦克的容器Blood b = new Blood();//实例化一个血块//实例化两个墙Wall w1=new Wall(300, 200, 20,150, this);Wall w2=new Wall(200, 100, 20,150, this);//双缓冲技术,消除频闪Image offScreenImage = null;public void update(Graphics g) {if(offScreenImage == null) {offScreenImage = this.createImage(GAME_WIDTH, GAME_HEIGHT);}Graphics gOffScreen = offScreenImage.getGraphics();Color c = gOffScreen.getColor();gOffScreen.setColor(Color.gray);gOffScreen.fillRect(0, 0, GAME_WIDTH, GAME_HEIGHT);gOffScreen.setColor(c);paint(gOffScreen);g.drawImage(offScreenImage, 0, 0, null);}public void paint(Graphics g)//会自动调用这个方法{  g.drawString("tanks    count:" + tanks.size(), 10, 35);g.drawString("explodes count:" + explodes.size(), 10, 50);g.drawString("missiles count:" + missiles.size(), 10, 65);g.drawString("Tank     life:" + myTank.getLife(), 10, 80);if(tanks.size() <= 0) {for(int i=0; i<5; i++) {tanks.add(new Tank(50 + 40*(i+1), 50, false, Tank.Direction.D, this));}}//把容器里面的子弹都画出来for(int i=0;i<missiles.size();i++){Missile m=missiles.get(i);m.hitTanks(tanks);//添加子弹打坦克的方法m.hitTank(myTank);m.hitTank(BossTank);m.hitWall(w1);        m.hitWall(w2);m.hitMissiles(missiles);//调用子弹撞子弹方法m.draw(g);}//把容器里面的爆炸全部画出来for(int i=0; i<explodes.size(); i++) {Explode e = explodes.get(i);e.draw(g);//e.ExplodehitTanks(tanks);//e.ExplodehitTank(BossTank);}//把容器里面的坦克全部画出来for(int i=0; i<tanks.size(); i++) {Tank t = tanks.get(i);t.collidesWithWall(w1);t.collidesWithWall(w2);t.collidesWithTanks(tanks);t.draw(g);}b.draw(g);//血块画出来BossTank.draw(g);BossTank.collidesWithWall(w1);BossTank.collidesWithWall(w2);BossTank.collidesWithTanks(tanks);//我方坦克画出来并添加方法myTank.draw(g);myTank.eat(b);       myTank.collidesWithWall(w1);myTank.collidesWithWall(w2);//画出墙来w1.draw(g);w2.draw(g);}//初始化游戏窗口的方法public void lauchFrame(){//初始化坦克,添加进容器for(int i=0;i<10;i++){tanks.add(new Tank(50+40*(i+1),50,false,Tank.Direction.D,this));}this.setLocation(300, 100);this.setSize(GAME_WIDTH,GAME_HEIGHT);this.setTitle("zz TankWar");this.addWindowListener(new WindowAdapter(){public void windowClosing(WindowEvent e){System.exit(0);}});this.setBackground(Color.GREEN);this.setResizable(false);this.addKeyListener(new KeyMonitor());this.setVisible(true);new Thread(new PaintThread()).start();}private class PaintThread implements Runnable{public void run(){while(true){repaint();try{Thread.sleep(50);}catch(InterruptedException e){e.printStackTrace();}}}}private class KeyMonitor extends KeyAdapter {//键盘监听public void keyReleased(KeyEvent e){myTank.keyReleased(e);}public void keyPressed(KeyEvent e) {myTank.keyPressed(e);}}public static void main(String[] args) {TankClient t=new TankClient();t.lauchFrame();}}

总结

其实坦克大战这种游戏很简单,只要懂一些基本的数据结构和碰撞检测,还有重绘的方法就能够打造属于自己的坦克大战,给自己童年一个华丽的蜕变。

基于java的坦克大战实例相关推荐

  1. 基于Java的坦克大战游戏的设计与实现(论文+PPT+源码)

    幻灯片1 基于Java的坦克大战游戏的设计与实现 幻灯片2 CONTENTS 1 4 设计工具与相关技术 详细设计 2 5 系统分析 结论 3 总体设计 幻灯片3 PPT模板下载:http://www ...

  2. 【JAVA程序设计】基于JAVA的坦克大战小游戏--入门级小游戏

    基于JAVA的坦克大战小游戏--入门级小游戏 零.项目获取 一.项目简介 二.开发环境 三.游戏玩法 四.运行截图 零.项目获取 获取方式(点击下载):是云猿实战 项目经过多人测试运行,可以确保100 ...

  3. java坦克大战登录界面设计_基于JAVA的坦克大战设计和实现-代码.doc

    JISHOU UNIVERSITY 本科生毕业设计 题 目:基于JAVA的坦克大战设计与实现作 者:学 号:所属学院:专业年级:指导教师:职 称:完成时间:2012年5月7日 吉首大学 基于JAVA的 ...

  4. Java练手项目2:基于Java的坦克大战游戏(学习Java必备!!!)

    1.引言 随着社会和时代的进步,来自各个方面的压力让人没精打采,为了分解人们的压力,休养那变得疲顿的头脑和劳累的身心,特设计了坦克大战小游戏,游戏操作非常容易,只要将手指放在键盘上敲击相关的游戏键就可 ...

  5. 基于java的坦克大战游戏-计算机毕业设计

    项目介绍 坦克游戏是在Eclipse环境下使用java编程.它的主要功能有:坦克能够四处移动,能够发射子弹打击敌人,敌人的坦克能够自由移动,能够产生模拟爆炸效果,能够产生障碍物,能够增长生命.本游戏有 ...

  6. 基于java的坦克大战游戏

    坦克游戏是在Eclipse环境下使用java编程.它的主要功能有:坦克能够四处移动,能够发射子弹打击敌人,敌人的坦克能够自由移动,能够产生模拟爆炸效果,能够产生障碍物,能够增长生命.本游戏有游戏主窗体 ...

  7. 基于java的坦克大战游戏系统毕业设计-5.0(论文设计+源码+PPT答辩).rar

    随着计算机的普及以及对电子游戏的认识, 电子游戏已被越来越多的人选作放松. 娱乐的休闲方式: 电子游戏既不需要专门购买游戏器材, 也不需要宽阔的游戏场地, 只需要一台能独立完成任务的计算机即可, 它可 ...

  8. 基于java的坦克大战游戏的开发设计与实现-(毕业论文+毕业设计源码+答辩PPT).rar

    随着计算机的普及以及对电子游戏的认识, 电子游戏已被越来越多的人选作放松. 娱乐的休闲方式: 电子游戏既不需要专门购买游戏器材, 也不需要宽阔的游戏场地, 只需要一台能独立完成任务的计算机即可, 它可 ...

  9. 基于Java的坦克大战游戏的设计与实现

    游戏由服务器端和客户端两部分组成. 在服务器端,ServerModel类主要用来创建主机,ServerView类主要负责服务器端图形界面的面板信息的设置,ServerControler类处理来自服务器 ...

最新文章

  1. 并发编程之多进程进程进程
  2. RuntimeError: cudnn64_7.dll not found.
  3. JEMTER简单的测试计划
  4. CSS+JS实现兼容性很好的无限级下拉菜单
  5. JavaScript-12(脚本化CSS)
  6. html文件转成base64字符串,js 转base64字符串为文件
  7. 高通Android平台下关于display部分的几个关键问题
  8. gitlab汉化及关联LDAP
  9. 法兰克机器人外部自动_行业数据 | 服务机器人销售额创新纪录:全球增长32
  10. html中label中的for属性
  11. 如何提升代码的安全性 —— 代码混淆
  12. 怀化市哪里有学计算机的,怀化汽修学校推荐-哪里好,计算机职业学校
  13. 音乐Npc弹窗 c#
  14. 苹果手机如何分享wifi密码_怎样用手机改wifi密码
  15. python爬取京东商品价格走势_用python编写的抓京东商品价格的爬虫
  16. 【MRCPv2协议介绍】 Generic Message Headers
  17. android 夜间模式代码,Android 超简单的夜间模式如何实现?
  18. 排列组合和二项式定理
  19. 面向对象编程是什么意思
  20. 半年巨亏10亿,水滴烧钱枯竭硬伤难愈

热门文章

  1. VB实现SQL Server 2000存储过程调用
  2. 苹果应用商店审核_苹果应用商店审核指南(中文版)-感谢译言网 - 苹果官方应用审核标准-中文版苹果官方应用审核标准...
  3. FastDFS网页访问文件特别慢
  4. 给没时间陪小宝宝的朋友
  5. python判断正负的函数_python判断正负数方式
  6. html css变成赛博朋克风格按钮
  7. OpenCV学习(69)
  8. html短信发送的方法
  9. Linux开机后黑屏无反应
  10. 微信小程序之豆瓣电影