1.主类
package s1230坦克大战;
import java.awt.Color;
import java.awt.Graphics;
import java.awt.event.KeyEvent;
import java.awt.event.KeyListener;
import java.util.Vector;
import javax.swing.ImageIcon;
import javax.swing.JFrame;
import javax.swing.JPanel;
import 工具类.ThreadSleep;
public class Tank1
extends JFrame {
static int panelXLength=700;
static int panelYlength=700;
static int gameXLength=500;
static int gameYLength=500;
static int zidanNum=0;
MyPanel mp=null;
public static void main
(String[] args
)
{
Tank1 t1=new Tank1();
}
public Tank1()
{ mp=new MyPanel();
this.add(mp);
this.setTitle("坦克大战"); //设置窗体的标题
this.setLocationRelativeTo(null); //设置窗体出现位置居中
this.setDefaultCloseOperation(3); //设置窗体的关闭操作
this.setResizable(true); //设置禁止调整窗体的大小
this.
setIconImage((new ImageIcon("E:/Michael/javaImage/扫雷图片/bomb.png").
getImage())); //设置标题栏图标
this.setSize(panelXLength,panelYlength); //设置窗体的大小
this.setLocationRelativeTo(null); //设置窗体出现在屏幕中间
this.addKeyListener(mp);
this.setVisible(true);
o.start(); //这个线程的作用是不断执行MyPanel
}
{
MyTank mt=null; //有什么作用?
Vector<EnemyTank> dtk=new Vector<EnemyTank>(); //new 出一个新的vector对象,vector多线程
int tankNum=3;
public MyPanel()
{
mt=new MyTank(250,400); //创建我方坦克
for(int i=0;i<tankNum;i++) //批量创建敌方坦克,要用到vector
{ EnemyTank dt=new EnemyTank((i)*180+5,10);
dtk.add(dt);
r.start();
}
}
{
super.paint(g);
g.fillRect(0,0,gameXLength,gameYLength);
this.drawTank(mt.getX(),mt.getY(),g,mt.leixing,mt.fangxiang); //在界面上绘制我方坦克,x(坐标),y(坐标),画笔g,类型,方向
for(int i=0;i<tankNum;i++) //在界面上批量绘制敌方坦克
{ if(dtk.get(i).life==true)
{this.drawTank(dtk.get(i).getX(),dtk.get(i).getY(),g,0,dtk.get(i).fangxiang); //x(坐标),y(坐标),画笔g,类型,方向
for(int j=0;j<dtk.get(i).dzd.size();j++)
{
Zidan zd=dtk.get(i).dzd.get(j);
dtk.get(i).shoot();
if(zd!=null&&zd.life==true) //mt.zd.life==true 控制子弹的范围
{
g.
setColor(Color.
RED); //设置子弹颜色
g.fill3DRect(zd.x, zd.y, 3,3, false); //绘制子弹,如何让子弹动起来
}
if(zd.life==false) //除去Vector中的zd对象,目的是为了实现子弹数量限制
dtk.get(i).dzd.remove(zd);
}
}
}
for(int i=0;i<mt.aa.size();i++) //绘制我方坦克子弹
{ Zidan zd=mt.aa.get(i);
if(zd!=null&&mt.zd.life==true) //mt.zd.life==true 控制子弹的范围
{
g.
setColor(Color.
RED); //设置子弹颜色
g.fill3DRect(zd.x, zd.y, 3, 3, false); //绘制子弹,如何让子弹动起来
}
if(zd.life==false) //除去Vector中的zd对象,目的是为了实现子弹数量限制
mt.aa.remove(zd);
}
}
//子弹是否击中tank的判断方法*************************************
public void jizhong(Zidan zd,EnemyTank dt)
{ switch(dt.fangxiang)
{
case 0:
case 1:
if(zd.x>dt.x&&zd.x<dt.x+20&&zd.y>dt.y&&zd.y<dt.y+30)
{ zd.life=false; dt.life=false;}
break;
case 2:
case 3:
if(zd.x>dt.x&&zd.x<dt.x+30&&zd.y>dt.y&&zd.y<dt.y+20)
{ zd.life=false; dt.life=false;}
break;
}
}
//子弹是否击中tank的判断方法*************************************
private void drawTank
(int x,
int y,
Graphics g,
int leixing,
int fangxiang
) //绘制坦克的方法
{
switch(leixing) //设置坦克颜色,0为黄色,1为绿色
{
case 0: g.
setColor(Color.
YELLOW);break;
case 1: g.
setColor(Color.
GREEN);break;
}
switch(fangxiang) //坦克方向,case0表示面朝上方的坦克,1表示面朝右方,2表示面朝下方,3表示面朝左方
{
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-3); //炮管:绝对长度为18
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-3, y+10); //炮管:绝对长度为18
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+33); //炮管:绝对长度为18
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+5, y+5, 10, 10); //椭圆炮台
g.drawLine(x+10, y+10, x+28, y+10); //炮管:绝对长度为18
break;
}
}
{ //坦克的方向控制,依次是上下左右,对应按键是w s a d。
{
this.mt.setFangxiang(0);
this.mt.upMove();
}
{ this.mt.setFangxiang(2);
this.mt.downMove();
}
{ this.mt.setFangxiang(1);
this.mt.leftMove();
}
{ this.mt.setFangxiang(3);
this.mt.rightMove();
}
if(e.
getKeyCode()==KeyEvent.
VK_J) //监听发射子弹的按钮
{ if(mt.aa.size()<8) //限制子弹发射的数量为8颗
this.mt.shoot();
}
this.repaint(); //还没搞懂这个是干嘛的?
}
public void run()
{
while(true)
{
ThreadSleep.threadSleep(100);
for(int i=0;i<mt.aa.size();i++) //2层循环的作用是,让每一颗子弹和每一辆坦克的坐标对比,来确定被打中的坦克
{ Zidan zd=mt.aa.get(i); //取出子弹
if(zd.life) //如果子弹有效
{
for(int j=0;j<dtk.size();j++)
{EnemyTank dt=dtk.get(j); //取出坦克对象
if(dt.life) this.jizhong(zd,dt);//判断子弹是否击中tank
}
}
}
this.repaint(); //还没搞懂这个是干嘛的?
}
}
}
}
2.sucai类
package s1230坦克大战;
import java.util.Random;
import java.util.Vector;
class Tank {
int x=0,y=0; //横纵坐标
int speed=9;
int fangxiang=0;
int leixing=1;
int time=0;
boolean life=true;
public Tank(int x,int y) //构造方法
{this.x=x;
this.y=y;
}
public int getSpeed() {return speed;}
public void setSpeed(int speed) {this.speed = speed;}
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 void upMove() {if(y>5) y-=speed;} //向上移动
public void downMove() {if(y<460)y+=speed;} //向下移动
public void leftMove() {if(x>5) x-=speed;} //向左移动
public void rightMove() {if(x<460)x+=speed;} //向右移动
public int getFangxiang() {return fangxiang;}
public void setFangxiang(int fangxiang) {this.fangxiang = fangxiang;}
public int getLeixing() {return leixing;}
public void setLeixing(int leixing) {this.leixing = leixing;}
}
class MyTank extends Tank
{ Vector<Zidan> aa=new Vector<Zidan>(); //专门存放子弹,来解决一按发射键子弹消失的问题
Zidan zd=null;
public MyTank(int x,int y)
{super(x,y);} //调用父类的构造方法
public void shoot()
{ switch(this.fangxiang)
{ case 0: zd=new Zidan(x+10,y,0); aa.add(zd);break; //每发射一颗子弹都加入到容器Vector中
case 1: zd=new Zidan(x,y+10,1); aa.add(zd);break;
case 2: zd=new Zidan(x+10,y+30,2); aa.add(zd);break;
case 3: zd=new Zidan(x+30,y+10,3); aa.add(zd);break;
}
t.start();
}
}
class EnemyTank
extends Tank
implements Runnable
{ int speed=1; //每次线程调用,坦克前进一次的距离
Zidan zd=null;
Vector<Zidan> dzd=new Vector<Zidan>(); //专门存放子弹,来解决一按发射键子弹消失的问题
public EnemyTank(int x,int y)
{super(x,y);} //调用父类的构造方法
public void shoot()
{ switch(this.fangxiang)
{ case 0: zd=new Zidan(x+10,y,0); dzd.add(zd);break; //每发射一颗子弹都加入到容器Vector中
case 1: zd=new Zidan(x,y+10,1); dzd.add(zd);break;
case 2: zd=new Zidan(x+10,y+30,2); dzd.add(zd);break;
case 3: zd=new Zidan(x+30,y+10,3); dzd.add(zd);break;
}
t.start();
}
public void run()
{
while(true)
{
int length;
this.
fangxiang=(int)(Math.
random()*4); //随机产生方向
switch(this.fangxiang)
{ case 0:
length=a.nextInt(59)+13; //每次随机方向,坦克前进的距离为 次数*speed,就是每次随机方向前进的总距离
for(int i=0;i<length;i++)
{
if(y>5)y-=speed;
else break;
try {Thread.
sleep(50);} //通过线程挂起的时间,控制地方坦克移动的频率,0.2秒前进一次
}
break;
case 1:
length=a.nextInt(59)+13; //每次随机方向,坦克前进的次数 次数*speed,就是每次随机方向前进的总距离
for(int i=0;i<length;i++)
{
if(x>5)x-=speed;
else break;
try {Thread.
sleep(50);} //通过线程挂起的时间,控制地方坦克移动的频率,0.2秒前进一次
}
break;
case 2:
length=a.nextInt(59)+13; //每次随机方向,坦克前进的次数 次数*speed,就是每次随机方向前进的总距离
for(int i=0;i<length;i++)
{
if(y<480)y+=speed;
else break;
try {Thread.
sleep(50);} //通过线程挂起的时间,控制地方坦克移动的频率,0.2秒前进一次
}
break;
case 3:
length=a.nextInt(59)+13; //每次随机方向,坦克前进的次数 次数*speed,就是每次随机方向前进的总距离
for(int i=0;i<length;i++)
{
if(x<470)x+=speed;
else break;
try {Thread.
sleep(50);} //通过线程挂起的时间,控制地方坦克移动的频率,0.2秒前进一次
}
break;
}
if(this.life==false) break; //如果坦克被子弹击中,那么就退出循环
Vector<Zidan> dzd=new Vector<Zidan>();
//坦克发子弹的代码
time++;
if(time%2==0)
{ if(life)
{
if(dzd.size()<5)
{ Zidan zd=null;
switch(fangxiang)
{
case 0: zd=new Zidan(x+10,y,0);
dzd.add(zd);
break;
case 1: zd=new Zidan(x+10,y,1);
dzd.add(zd);
break;
case 2: zd=new Zidan(x+10,y,2);
dzd.add(zd);
break;
case 3: zd=new Zidan(x+10,y,3);
dzd.add(zd);
break;
}
t5.start();
}
}
}
}
}
}
{ int x,y;
int fangxiang;
int speed=9;
boolean life=true;
public Zidan(int x,int y,int fangxiang)
{this.x=x;
this.y=y;
this.fangxiang=fangxiang;
}
public void run()
{
while(true) //线程下面有死循环都要有休眠时间
{
switch(fangxiang)
{ 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>500) //子弹出了游戏边界就自动就将生命值设为false
{this.life=false; break;}
}
}
}