gui坦克大战(初级版本)

2 篇文章 0 订阅
只实现了可以用wasd来控制坦克的移动,控制了自己的坦克发射子弹,
敌方坦克可以自由发射子弹,子弹速度,敌方坦克可以自由移动,
敌方坦克在击中我,以及我击中敌方坦克后坦克会爆炸等等的操作		
(主要运用了面向对象,gui,以及多线程这些方面的知识。)

思路在代码中都很详细

主类:

package MyTankGame7;
/*7.0版本
 * 目的:		①:添加监听
 * 			②:子弹连发
 * 			③:最多只能连发5颗
 *			④:我方的坦克击中敌人的坦克,敌人的坦克可以消失
 *			5.爆炸地效果
 *			6.敌人的坦克做成线程,并且可以自己随机地乱动
 *			7.控制坦克可以在指定地范围内活动
 *			8.让敌人的子弹在击中我方坦克的时候,我方的坦克也可以爆炸
 *  过程:定义一个击中敌人的方法。
 * */
import java.awt.Color;
import java.awt.Graphics;
import java.awt.Image;
import java.awt.Panel;
import java.awt.Toolkit;
import java.awt.event.KeyEvent;
import java.awt.event.KeyListener;
import java.util.Vector;

import javax.swing.JFrame;
import javax.swing.JPanel;
public class Tankgame7 extends JFrame {	
	MyPanel mp=null;
	
	public Tankgame7(){
		mp=new MyPanel();
		//启动线程
		Thread t=new Thread(mp);
		t.start();
		this.add(mp);
		//注册监听
		this.setTitle("坦克大战");
		this.addKeyListener(mp);
		this.setSize(400,300);
		this.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
		this.setVisible(true);
	}

	
	public static void main(String[] args) {
		new Tankgame7();
	}


}


class MyPanel extends JPanel implements KeyListener,Runnable {	//panel面板
	Hero hero=null;
	//声明三张图片,三张图片的切换,才能组成一个炸弹      (不是某一个坦克特有的属性)
	Image image1=null;
	Image image2=null;
	Image image3=null;
	
	//定义炸弹的集合
	Vector<Bomb>bombs=new Vector<Bomb>();
	
	
	
	
	
	Vector<EnemyTank>ets=new Vector<EnemyTank>();
	int ensize=7;
	
	
	public MyPanel(){
		image1=Toolkit.getDefaultToolkit().getImage(Panel.class.getResource("/a.jpg"));
		image2=Toolkit.getDefaultToolkit().getImage(Panel.class.getResource("/b.jpg"));
		image3=Toolkit.getDefaultToolkit().getImage(Panel.class.getResource("/c.jpg"));
		
		
		hero=new Hero(100, 100);
		//初始化敌人的坦克
		for(int i=0;i<ensize;i++){
			//创建一辆敌人的坦克对象,并且加入集合
		EnemyTank et=new EnemyTank((i+1)*50, 0);
				et.setColor(0);
				et.setDirect(2);
				ets.add(et);
				
				//启动敌人地坦克线程
				Thread t=new Thread(et);
				t.start();
				
				Shot s=new Shot(et.x+10, et.y+30, 2);
				et.ss.add(s);		//添加到集合‘
				Thread t2=new Thread(s);
				t2.start();		//让敌人也可以去发射子弹
				
				
				
				
		}
	}
	
	public void paint(Graphics g){	//画坦克
		super.paint(g);
		g.fillRect(0, 0, 400, 300);
//		g.setColor(Color.CYAN);
		//画坦克的方法
		if(hero.isLive){
			
			this.drawTank(hero.getX(), hero.getY(), g, hero.getDirect(), 1);
		}
		
		//画子弹		方法:遍历集合,取出子弹
		for(int i=0;i<hero.ss.size();i++){
			Shot myshot=this.hero.ss.get(i);
			if(myshot!=null&&myshot.isLive==true){
				g.draw3DRect(myshot.x,myshot.y, 2, 2, false);
			}
			if(myshot.isLive==false){		//如果子弹死亡,就从原来的集合里面拿出这个死亡的子弹
				hero.ss.remove(myshot);	//这样就可以保证子弹的数量总共是5颗
			}
			
		}
		
		
		
		//画出炸弹
			for(int i=0;i<bombs.size();i++){
				//取出炸弹
				Bomb b=bombs.get(i);
				if(b.life>6){
					g.drawImage(image1, b.x, b.y, 30, 30, this);
				}else if(b.life>3){
					g.drawImage(image2, b.x, b.y, 30, 30, this);
					
				}else{
					g.drawImage(image3, b.x, b.y, 30, 30, this);
					
				}
				//让炸弹的生命值减少
				b.lifeDown();
				//如果炸弹的生命值减少为0,就把这个炸弹从bombs向量中移除
				if(b.life==0){
					bombs.remove(b);
				}
				
				
				
			}
		
		
		
		
		
		//画敌人的坦克
		for(int i=0;i<ets.size();i++){
			EnemyTank et=ets.get(i);
			if(et.isLive){
				this.drawTank(ets.get(i).getX(), ets.get(i).getY(), g,ets.get(i).getDirect() , 0);
				
				//顺便画出敌人的子弹
				for(int j=0;j<et.ss.size();j++){
					//取出子弹
					Shot enemyShot=et.ss.get(j);
					if(enemyShot.isLive){
						g.draw3DRect(enemyShot.x, enemyShot.y, 2, 2, false);
						
					}else{
						//如果敌人的坦克死亡了,就从向量里面删除了
						et.ss.remove(enemyShot);
						
					}
					
				}
				
				
			}
		}
	}
	public void hitEnemyTank(){
		//  !!!!!!!!!!!!         !!!!!!! 判断是否击中敌人的坦克    (要把每一颗子弹都和坦克的坐标做比较)
		for(int i=0;i<hero.ss.size();i++){
			//取出子弹
			Shot myshot=hero.ss.get(i);
			//判断子弹是否有效
			if(myshot.isLive){
				//取出每个敌人的坦克,与它判断
				for(int j=0;j<ets.size();j++){
					//取出坦克
					EnemyTank et=ets.get(j);
					if(et.isLive){
						this.hitTank(myshot, et);
					}
				}
			}
		}
	}
	
	//敌人的子弹是否击中了我
	public void hitMe(){
		//取出每一个敌人的坦克
		for(int i=0;i<this.ets.size();i++){
			//取出坦克
			EnemyTank et=ets.get(i);
			
			//取出每一颗子弹
			for(int j=0;j<et.ss.size();j++){
				
				//取出子弹
				Shot enemyShot=et.ss.get(j);
				
				this.hitTank(enemyShot, hero);
			}
			
			
			
		}
		
	}
	
	
	//击中目标的函数
	public void hitTank(Shot s,Tank et){
		//根据方向来判断
		switch(et.direct){
		case 0: 
		case 2:
			if(s.x>et.x&&s.x<et.x+20&&s.y>et.y&&s.y<et.y+30){
				//击中目标
				s.isLive=false;
				et.isLive=false;
				Bomb b1=new Bomb(et.x, et.y);
				bombs.add(b1);
			}
			break;
		case 1:
		case 3:
			if(s.x>et.x&&s.x<et.x+30&&s.y>et.y&&s.y<et.y+20){
				s.isLive=false;
				et.isLive=false;
				Bomb b=new Bomb(et.x, et.y);
				bombs.add(b);
			}
			break;
			
		
		}
		
		
	}
	
	
	
	
	//画出坦克的函数
	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.YELLOW);
			break;
		}
		//判断方向
		switch(direct){
		case 0:	//向上走
			//左面的坦克
			g.fill3DRect(x, y, 5, 30, false);
			g.fill3DRect(x+15, y, 5, 30, false);
			g.fill3DRect(x+5, y+5, 10, 20, false);
			g.fillOval(x+5, y+10, 10, 10);
			g.drawLine(x+10, y+15, x+10, y);
			break;
		case 1:	//向右边
			g.fill3DRect(x, y, 30, 5, false);
			g.fill3DRect(x, y+15, 30, 5, false);
			g.fill3DRect(x+5, y+5, 20, 10, false);
			g.fillOval(x+10, y+5, 10, 10);
			g.drawLine(x+15, y+10, x+30, y+10);
			break;
		case 2:	//向下边
			g.fill3DRect(x, y, 5, 30, false);
			g.fill3DRect(x+15, y, 5, 30, false);
			g.fill3DRect(x+5, y+5, 10, 20, false);
			g.fillOval(x+5, y+10, 10, 10);
			g.drawLine(x+10, y+15, x+10, y+30);
			break;
			
		case 3: 		//向左边
			g.fill3DRect(x, y, 30, 5, false);
			g.fill3DRect(x, y+15, 30, 5, false);
			g.fill3DRect(x+5, y+5, 20, 10, false);
			g.fillOval(x+10, y+5, 10, 10);
			g.drawLine(x+15, y+10, x	, y+10);
			break;
			
			
			
		}
		
	}

	@Override
	/*
	 * 
	 * 
	 * */
	public void keyPressed(KeyEvent arg0) {	//0向上,1向右,2向下,3向左
		// TODO Auto-generated method stub
		if(arg0.getKeyCode()==KeyEvent.VK_W){
			this.hero.setDirect(0); //上
			hero.moveup();
		}
		else if(arg0.getKeyCode()==KeyEvent.VK_D){
			this.hero.setDirect(1);
			this.hero.moveright();
		}else if(arg0.getKeyCode()==KeyEvent.VK_S){
			this.hero.setDirect(2);
			hero.movedown();
		}else if(arg0.getKeyCode()==KeyEvent.VK_A){
			this.hero.setDirect(3);
			hero.moveleft();
		}
		if(arg0.getKeyCode()==KeyEvent.VK_J){
			if(hero.ss.size()<=4){
				this.hero.shotEnemy();
				
				
				
			}
			
			
		}
		//必须重新绘制panel
		this.repaint();
	}

	@Override
	public void keyReleased(KeyEvent arg0) {
		// TODO Auto-generated method stub
		
	}

	@Override
	public void keyTyped(KeyEvent arg0) {
		// TODO Auto-generated method stub
		
	}

	@Override
	public void run() {
		// TODO Auto-generated method stub
		//每隔100ms去重画
		while(true){
			try {
				Thread.sleep(100);
			} catch (InterruptedException e) {
				// TODO Auto-generated catch block
				e.printStackTrace();
			}
			
			//判断是否击中
			this.hitEnemyTank();
			//判断敌人的子弹是否击中我了
			this.hitMe();
			
			//判断是否需要给坦克加入新的子弹
			
			this.repaint();
			for(int i=0;i<ets.size();i++){
				EnemyTank et=ets.get(i);
				if(et.isLive){
					
					if(et.ss.size()<5){		//敌人的坦克子弹总共4颗
						Shot s=null;
						//没有子弹
						//添加子弹
						switch(et.direct){
						case 0:
							s=new Shot(et.x+10, et.y,0);
							et.ss.add(s);				//添加子弹
							break;
						case 1:
							s=new Shot(et.x+30, et.y+10,1);
							et.ss.add(s);
							break;
						case 2:
							s=new Shot(et.x+10, et.y+30,2);
							et.ss.add(s);
							break;
						case 3:
							s=new Shot(et.x, et.y+10,3);
							et.ss.add(s);
							break;
						}
						
						
						//启动子弹的线程,否则子弹是死的
						Thread t=new Thread(s);
						t.start();
					}
				}
			}
		}
	}
}


成员类

package MyTankGame7;

import java.util.Vector;

/*
 * 
 *动态的做成线程,不会动的,就可以做成静态的 
 * */
class Bomb{			//炸弹类
	int x;
	int y;
	int life=9;		//做成爆炸		(炸弹的生命)
	boolean isLive=true;
	
	public Bomb(int x,int y){
		this.x=x;
		this.y=y;
	}
	//减少生命
	public void lifeDown(){
		if(life>0){
			life--;
		}else{
			this.isLive=false;
			
		}
	}
	
	
	
}


class Tank{			//坦克的父类
	int x;
	int y;
	//方向
	int direct=0; //	0表示上,1表示右,2表示下,3表示左
	
	int speed=3;	//默认初始化的速度 1px
	
	int color;
	
	boolean isLive=true;
	
	public int getSpeed() {
		return speed;
	}
	public void setSpeed(int speed) {
		this.speed = speed;
	}
	public int getColor() {
		return color;
	}
	public void setColor(int color) {
		this.color = color;
	}
	public int getDirect() {
		return direct;
	}
	public void setDirect(int direct) {
		this.direct = direct;
	}
	public int getX() {
		return x;
	}
	public void setX(int x) {
		this.x = x;
	}
	public int getY() {
		return y;
	}
	public void setY(int y) {
		this.y = y;
	}
	public Tank(int x,int y){
		this.x=x;
		this.y=y;
	}
}
//敌人的坦克,把敌人的坦克升级成为线程类
class EnemyTank extends  Tank implements Runnable{
	//定义敌人的子弹的集合
	Vector<Shot>ss=new Vector<Shot>();
	
	
	
//	boolean isLive=true;	//坦克是否活着
	
	
	public EnemyTank(int x, int y) {
		super(x, y);
		// TODO Auto-generated constructor stub
	}


	@Override
	public void run() {		//让敌人的坦克可以自己动
		// TODO Auto-generated method stub
		while(true){
			try{
				Thread.sleep(100);
			}catch(Exception e){
				e.printStackTrace();
			}
	
			
			switch(this.direct){//0向上,1向右,2向下,3向左'
			case 0:	
				if(y>0){			//国定一下活动的范围
					
					for(int i=0;i<30;i++){		//让敌人地坦克比较平滑地运动1s多变换一次方向
						this.y-=speed;
						try{
							Thread.sleep(50);
						}catch(Exception e){
							e.printStackTrace();
						} //try 的
					}
				}
				break;
			case 1:
				if(x<400){
					
					for(int i=0;i<30;i++){
						this.x+=speed;
						try{
							Thread.sleep(50);
						}catch(Exception e){
							e.printStackTrace();
						} //try 的
					}
				}
				break;
			case 2:
				if(y<300){
					
					for(int i=0;i<30;i++){
						this.y+=speed;
						try{
							Thread.sleep(50);
						}catch(Exception e){
							e.printStackTrace();
						} //try 的
					}
				}
				break;
			case 3:
				if(x>0){
					
					for(int i=0;i<30;i++){
						this.x-=speed;
						try{
							Thread.sleep(50);
						}catch(Exception e){
							e.printStackTrace();
						} //try 的
					}
				}
				break;
			}
			//判断子弹是否没有了  (在方向还没有随机改变之前就给它创建)
			if(ss.size()<1)
			{
				
			}
			
			//让坦克产生一个新的随机方向
			this.direct=(int) (Math.random()*4);	//0--3范围内
			
			
			//判断敌人是否死亡了
			if(this.isLive==false){
				
				break;//让坦克死亡后退出线程  (僵尸进程)
			}
			
			
			
			
			
		}	//while 的
	
	
		
	}//run 的
	
}

class Hero extends Tank{	//我的坦克
	Vector<Shot>ss=new Vector<>();				//集合,将子弹添加到集合中去
	Shot s=null;						//声明一个子弹对象
	
	public Hero(int x, int y) {
		super(x, y);
		// TODO Auto-generated constructor stub
		this.setSpeed(8);
		
	}
	
	public void moveup(){	 //坦克向上移动
		this.y-=speed;
	}
	public void movedown(){	//向上移动
		this.y+=speed;
	}
	public void moveright(){		//向右移动
		this.x+=speed;
	}
	public void moveleft(){		//向左移动
		this.x-=speed;
	}

	public void shotEnemy(){
		
	switch(this.direct){			//子弹不同的方向
	case 0:
		s=new Shot(x+10, y,0);
		ss.add(s);				//添加子弹
		break;
	case 1:
		s=new Shot(x+30, y+10,1);
		ss.add(s);
		break;
	case 2:
		s=new Shot(x+10, y+30,2);
		ss.add(s);
		break;
	case 3:
		s=new Shot(x, y+10,3);
		ss.add(s);
		break;
		
		
		
	}
	Thread t=new Thread(s);
	t.start();
	}
	}

class Shot implements Runnable{
	int x;
	int y;
	int direct;
	int speed=10;
	boolean isLive=true;
	public Shot(int x,int y,int direct){
		this.x=x;
		this.y=y;
		this.direct=direct;
	}
	@Override
	public void run() {
		// TODO Auto-generated method stub
		while(true){
			try {
				Thread.sleep(50);
			} catch (InterruptedException e) {
				// TODO Auto-generated catch block
				e.printStackTrace();
			}
			switch(direct){
			case 0:
				y-=speed;
				break;
			case 1:
				x+=speed;
				break;
			case 2:
				y+=speed;
				break;
			case 3:
				x-=speed;
				break;
			}
			//子弹何时死亡
			
			//判断该子弹是否碰到墙壁
			if(x<0||x>500||y<0||y>400){		//子弹死亡
				this.isLive=false;
				break;
			}
		}
	}
	
	
}


坦克爆炸的图片:
在这里插入图片描述
在这里插入图片描述
在这里插入图片描述

效果:
在这里插入图片描述

在这里插入图片描述在这里插入图片描述

  • 2
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值