博客
关于我
强烈建议你试试无所不能的chatGPT,快点击我
Java小项目--坦克大战(version1.0)
阅读量:7071 次
发布时间:2019-06-28

本文共 9692 字,大约阅读时间需要 32 分钟。

Java小项目--坦克大战<TankWar1.0>

这个小项目主要是练习j2se的基础内容和面向对象的思想。项目实现了基本的简单功能,我方一辆坦克,用上下左右键控制移动方向,按F键为发射炮弹,敌方有10辆坦克,我方阵亡或者敌方挂光了游戏就结束了。用大小实心圆表示坦克和炮弹。这是最初版本,界面不够友好图形很土鳖,没有网络功能。在后续版本中会添加更炫的图片和网络功能,并加入聊天室,可以局域网内聊天和对战。

效果图:

项目包括4个文件,我把它们贴出来。

文件一:TankClient.java

TankClient为一个类,他的作用就像大管家,将坦克、炮弹、爆炸联系起来。首先是建立界面,然后重写了画图的paint方法,系统循环自动调用paint,所以在paint中调用坦克、炮弹、爆炸类各自的draw方法将各自画出来,而坦克、炮弹各自的draw是如何实现的画了什么大管家是不管它的,这也正是面向对象语言的一个思想。

Java的集合可以装对象,3个List容器分别装敌方坦克,所有炮弹,所有爆炸;

 

/* * 版本: version0.9 * 功能: @添加爆炸效果,添加多辆坦克*/	import java.awt.*;import java.awt.event.*;import java.io.*;import java.util.List;import java.util.*;public class TankClient extends Frame{		public final int SCREENWIDTH=800,SCREENHEIGHT=600; 	Tank myTank = new Tank(130,230,true,this);	//new了一辆坦克出来,第3个参数分别是我方坦克还是敌方坦克。		Missile missile=null;	Image screenImage = null;	List
missiles = new ArrayList
(); //这个容器装炮弹,任何坦克每打出一发炮弹都装进这个容器中,当炮弹击中对方坦克或者炮弹出界都将该//炮弹从容器中remove; List
explodes = new ArrayList
(); List
tanks = new ArrayList
(); public void update(Graphics g) { if(screenImage == null) screenImage = this.createImage(SCREENWIDTH,SCREENHEIGHT); Graphics graphics = screenImage.getGraphics(); Color c = graphics.getColor(); graphics.setColor(new Color(150,240,215)); graphics.fillRect(0, 0, SCREENWIDTH, SCREENHEIGHT); graphics.setColor(c); paint(graphics); g.drawImage(screenImage, 0, 0, null); } public void paint(Graphics g) { g.drawString("Missiles Counts: "+missiles.size(), 30, 50); g.drawString("Explodes Counts: "+explodes.size(), 30, 70); g.drawString("Tanks Counts: "+tanks.size(), 30, 90); myTank.draw(g); // enemyTank.draw(g); for(int i=0;i

 

文件二:Tank.java

Tank类包含坦克的一些属性,包括坦克的尺寸、速度、位置等,也包含一些方法包括开火fire方法、移动后坐标的计算、按键的处理。

 

import java.awt.*;import java.awt.event.*;import java.util.*;public class Tank {	int x,y; 	TankClient tc=null;	private boolean good = true;  //用来分辨敌我坦克,若某坦克good属性为true则该坦克为我方坦克		boolean live = true;    //用来表明该坦克是否还存活,若live属性为false表示该坦克已死则在draw方法里不将该坦克画出来并从list容器中移除。		public static final int SCREENWIDTH=800,SCREENHEIGHT=600; 	public static final int WIDTH=30,HEIGHT=30;	public static final int XSPEED=5,YSPEED=5;	boolean bL=false,bR=false,bU=false,bD=false,bB=false;	enum Direction { L,LD,LU,U,D,R,RD,RU,STOP };   //枚举类型,用来表示坦克的运动方向也决定了炮弹的方向	private Direction dir=Direction.STOP,mdir=Direction.RD;	private static Random r = new Random();  //定义的随机数	private static int dm = r.nextInt(12)+3;  	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,TankClient tc) {		this.x = x;		this.y = y;		this.good = good;		this.tc = tc;	}    	public Tank(int x, int y,boolean good,Direction dir,TankClient tc) {		this.x = x;		this.y = y;		this.good = good;		this.dir = dir;		this.tc = tc;	}		public boolean isGood() {		return good;	}	public boolean isLive() {		return live;	}		public void setLive(boolean live) {		this.live = live;	}			public void draw(Graphics g) {		if(!this.isLive()) {			if(!good)				tc.tanks.remove(this);				//如果该坦克是敌方坦克,而且死了,则将该坦克从容器中移除。 							return;		}				Color c = g.getColor();		if(good)			g.setColor(new Color(100,25,200));   //敌方坦克和我方坦克画成不同的颜色		else			g.setColor(Color.red);		g.fillOval(x, y, WIDTH, HEIGHT);		g.setColor(Color.blue);			move();				switch(mdir) {      //画该坦克的炮台,炮台的方向为坦克的最后运动方向,如果坦克为stop状态则保持上次方向。		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 LD:			g.drawLine(x+Tank.WIDTH/2, y+Tank.HEIGHT/2, x, y+Tank.HEIGHT);			break;		case R:			g.drawLine(x+Tank.WIDTH/2, y+Tank.HEIGHT/2, x+Tank.WIDTH, y+Tank.HEIGHT/2);			break;		case RU:			g.drawLine(x+Tank.WIDTH/2, y+Tank.HEIGHT/2, x+Tank.WIDTH, y);			break;		case RD:			g.drawLine(x+Tank.WIDTH/2, y+Tank.HEIGHT/2, x+Tank.WIDTH, y+Tank.HEIGHT);			break;		case U:			g.drawLine(x+Tank.WIDTH/2, y+Tank.HEIGHT/2, x+Tank.WIDTH/2, y);			break;		case D:				g.drawLine(x+Tank.WIDTH/2, y+Tank.HEIGHT/2, x+Tank.WIDTH/2, y+Tank.HEIGHT);			break;		case STOP:			break;					}				g.setColor(c);				}	public Missile fire() {						int x = this.x + Tank.WIDTH/2 - Missile.WIDTH/2;		int y = this.y + Tank.HEIGHT/2 - Missile.HEIGHT/2;			//根据坦克的和位置运动方向画出炮弹的位置和方向,第四个属性表示炮弹的敌我属性和坦克的敌我属性一致,坦克的good为true则打出的炮弹也为true。		Missile m = new Missile(x,y,mdir,good,this.tc);  		tc.missiles.add(m);	//将炮弹加入进容器			return m; //返回该炮弹	}	public void move() {				switch(dir) {  //根据方向对坦克位置进行更新		case L: 			x -=XSPEED;			break;		case LU:			x -=XSPEED;			y -=YSPEED;			break;		case LD:			x -=XSPEED;			y +=YSPEED;			break;		case R:			x +=XSPEED;			break;		case RU:			x +=XSPEED;			y -=YSPEED;			break;		case RD:			x +=XSPEED;			y +=YSPEED;			break;		case U:			y -=YSPEED;			break;		case D:				y +=YSPEED;			break;		case STOP:			break;				}				if(x<0)    //坦克不能出界			x=0;		else if(x>tc.SCREENWIDTH-Tank.WIDTH)			x=tc.SCREENWIDTH-Tank.WIDTH;		if(y<30)			y=30;		else if(y>tc.SCREENHEIGHT-Tank.HEIGHT)			y=tc.SCREENHEIGHT-Tank.HEIGHT;	//	dir = Direction.STOP; //加了这句速度很慢啊。		if(!good) {    //如果为敌方坦克,则运动方向为随机的。			Direction [] dirs = Direction.values();			int rn = r.nextInt(dirs.length-1);			dm--;           //注意dirs[dirs.length]为STOP。			if(dm<=0) {				dir = dirs[rn]; 				mdir = dir;				dm=r.nextInt(15)+3;			}				if(r.nextInt(50)>48) this.fire();					}							}		public void locationDir() {    //根据按下的按键决定方向		if(bR && !bL && !bU && !bD) {			dir = Direction.R;						}		else if(bR && !bL && bU && !bD)			dir = Direction.RU;		else if(bR && !bL && !bU && bD)			dir = Direction.RD;		else if(!bR && bL && !bU && !bD)			dir = Direction.L;		else if(!bR && bL && bU && !bD)			dir = Direction.LU;		else if(!bR && bL && !bU && bD)			dir = Direction.LD;		else if(!bR && !bL && bU && !bD)			dir = Direction.U;		else if(!bR && !bL && !bU && bD)			dir = Direction.D;		else			dir = Direction.STOP;				if(dir != Direction.STOP)  //mdir保存最后一次方向,坦克停下来了保持最后的方向。			mdir=dir;	}		public void KeyPress(KeyEvent e) {						int key = e.getKeyCode();		switch(key) {		case KeyEvent.VK_RIGHT:			System.out.println("R"); 			bR = true;	 			break;		case KeyEvent.VK_LEFT:			bL = true;			break;					case KeyEvent.VK_UP:			System.out.println("U");			bU = true;			break;		case KeyEvent.VK_DOWN:			System.out.println("D");			bD = true;				break;				}		locationDir();	}	public void keyReleased(KeyEvent e) {		int key = e.getKeyCode();		switch(key) {		case KeyEvent.VK_RIGHT:			System.out.println("R"); 			bR = false;	 			break;		case KeyEvent.VK_LEFT:			bL = false;			break;					case KeyEvent.VK_UP:			System.out.println("U");			bU = false;			break;		case KeyEvent.VK_DOWN:			System.out.println("D");			bD = false;				break;		case KeyEvent.VK_F:			System.out.println("F");			if(this.isLive())    //坦克存活时才能发子弹。				tc.missile = fire();				break;				}		locationDir();			}		public Rectangle getRec() {		return new Rectangle(x,y,Tank.WIDTH,Tank.HEIGHT);	}	}

 

文件三:Missile.java

炮弹类包含炮弹的属性和方法:尺寸、速度、位置、方向;坐标的计算,击打坦克等;

 

import java.awt.*;import java.util.List;import java.util.*;public class Missile {		int x,y;	TankClient tc;	Tank.Direction dir =Tank.Direction.R;	public static final int XSPEED=10,YSPEED=10;	public static final int WIDTH=10,HEIGHT=10;	private boolean live = true;	private boolean good;		public boolean isGood() {		return good;	}		public boolean isLive() {		return live;	}		public Missile(int x, int y, Tank.Direction dir) {		this.x = x;		this.y = y;		this.dir = dir;	}		public Missile(int x, int y, Tank.Direction dir,boolean good,TankClient tc) {		this.x = x;		this.y = y;		this.dir = dir;		this.good = good;   //tank的good属性和炮弹的good属性一致;		this.tc = tc;	}		public void draw(Graphics g) {		if(!this.live) {  //如果炮弹已死则将它从容器中移除并返回,不在把他画出来。			tc.missiles.remove(this);			return;		}							Color c = g.getColor();		if(!this.isGood())			g.setColor(Color.red);		else			g.setColor(new Color(100,25,200));		g.fillOval(x, y, WIDTH, HEIGHT);		g.setColor(c);			move();	}	public void move() {		if(dir == Tank.Direction.STOP)		System.out.println("@@@@@@@@@@@@@@@@");  									//测出bug,敌人坦克发出来停止的哑弹。		switch(dir) {		case L: 			x -=XSPEED;			break;		case LU:			x -=XSPEED;			y -=YSPEED;			break;		case LD:			x -=XSPEED;			y +=YSPEED;			break;		case R:			x +=XSPEED;			break;		case RU:			x +=XSPEED;			y -=YSPEED;			break;		case RD:			x +=XSPEED;			y +=YSPEED;			break;		case U:			y -=YSPEED;			break;		case D:				y +=YSPEED;			break;				}		System.out.println(x+"=x,y= "+y);		if(x<0 || y<30 || x>tc.SCREENWIDTH-10 || y>tc.SCREENHEIGHT-10) {			this.live = false;	//如果炮弹出界则死亡			}				}		public Rectangle getRec() {		return new Rectangle(x,y,WIDTH,HEIGHT);	}		public boolean hitTank(Tank t) {		if(this.getRec().intersects(t.getRec()) && t.isLive() 				&& this.good!=t.isGood()) {			t.setLive(false);			this.live = false;			Explode e = new Explode(x,y,this.tc);			e.setLive(true); 			tc.explodes.add(e);			return true;					}				return false;	}		public boolean hitTanks(List
tanks) { for(int i=0;i

 

文件四:Explode.java

爆炸效果类就是画几个圈,主要包含draw方法,当发生爆炸的时候将爆炸效果draw出来。

 

import java.awt.*;public class Explode {	int x,y;	private boolean live = false;	public boolean isLive() {		return live;	}	public void setLive(boolean live) {		this.live = live;	}	TankClient tc;	int [] diameter = {4,8,12,22,34,32,20,13,6};	int step = 0;		public Explode(int x,int y,TankClient tc) {		this.x = x;		this.y = y;		this.tc = tc;			}		public void draw(Graphics g) {		if(!this.live) {				tc.explodes.remove(this);						return;		}		if(step==diameter.length) {			step = 0;			this.live = false;			tc.explodes.remove(this);		}			Color c = g.getColor();		g.setColor(Color.GREEN);		g.fillOval(x, y, diameter[step], diameter[step]);		g.setColor(c);			step++;	}	}

 

 

你可能感兴趣的文章
android手机在slackware linux上的调试
查看>>
mysql性能优化配置
查看>>
JavaScript继承方式详解
查看>>
解决win7旗舰版无法打开微软论坛
查看>>
烂泥:高负载均衡学习haproxy之安装与配置
查看>>
第一个OC的类
查看>>
LeetCode:448. Find All Numbers Disappeared in an Array
查看>>
BarTender条码检验位类型知识讲解
查看>>
过滤器(登录认证)
查看>>
kernel(一) interrupts
查看>>
SQLite数据库约束详解
查看>>
form submit不进入action方法问题
查看>>
c#语言中 (int)、int.Parse()、int.TryParse、Convert.ToInt32的区别
查看>>
kbmMWClientQuery 排序问题
查看>>
WPF中的容器控件——WrapPanel
查看>>
初学CI源码
查看>>
获取数据库内容一
查看>>
移动端知识梳理
查看>>
在CentOS 7中部署Tomcat
查看>>
滚动时div的背景图片随之滚动
查看>>