package game;
/**
* 作者:郑云飞
* 内容:坦克大战项目实战
* 2010年8月20日画出坦克
* 2010年8月21日:让坦克动起来
* 2010年8月22日:让坦克发射子弹
* 2010年8月22日22:45分:让坦克能够连发子弹
*
*/
import java.awt.Color;
import java.awt.Graphics;
import java.awt.Image;
import java.awt.Toolkit;
import java.awt.event.KeyEvent;
import java.awt.event.KeyListener;
import java.io.File;
import java.util.Vector;
import javax.imageio.ImageIO;
import javax.swing.JFrame;
import javax.swing.JPanel;
@SuppressWarnings("serial")
public class MyTankGame1 extends JFrame
{
MyPanel1 mp=null;
//构造函数初始化成员变量
public MyTankGame1()
{
mp=new MyPanel1();
Thread t=new Thread(mp);
t.start();
this.add(mp);//将画板添加到当前的Jframe中
//注册监听事件
this.addKeyListener(mp);
this.setSize(800, 600);//设置窗体的大小
this.setBackground(Color.lightGray);
this.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);//窗口关闭时程序退出
this.setVisible(true);
}
public static void main(String[] args)
{
@SuppressWarnings("unused")
MyTankGame1 mt=new MyTankGame1();
}
}
//我的面板
@SuppressWarnings("serial")
class MyPanel1 extends JPanel implements KeyListener,Runnable
{
//定义一个我的坦克
Hero hero =null;
//第一敌人的坦克数组
Vector<EnemyTank> ets=new Vector<EnemyTank>();
int etSize=10;//定义敌人坦克的数量
//定义zhadan集合
Vector<Bomb> bombs=new Vector<Bomb>();
//定义三张图片,才能组成一个zhadan
Image image1=null;
Image image2=null;
Image image3=null;
Image image4=null;
Image tank_up=null;
Image tank_down=null;
Image tank_left=null;
Image tank_right=null;
Image zidan_img=null;
Image EnemyTank_up=null;
Image EnemyTank_down=null;
Image EnemyTank_right=null;
Image EnemyTank_left=null;
//构造函数初始化成员变量
public MyPanel1()
{
hero=new Hero(385,300,0);//初始化我的坦克开始出现的位置
init_img();//初始化图像
init_EnemyTank();//初始化敌人的坦克
}
private void init_map(Graphics g)
{
int [][]map=new int[][]{
{1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1},
{1,9,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,1},
{1,0,2,2,2,2,0,0,2,2,2,2,0,0,0,0,0,0,0,1},
{1,0,0,0,0,0,0,0,2,0,0,2,0,1,1,1,1,0,0,1},
{1,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,1},
{1,2,2,2,2,2,2,2,0,0,0,0,0,0,0,2,2,0,0,1},
{1,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,2,2,0,1},
{1,0,1,1,1,1,3,3,3,3,0,0,0,0,0,0,0,2,0,1},
{1,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,1},
{1,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,1},
{1,0,0,2,2,2,2,0,0,0,0,0,0,0,0,0,0,0,0,1},
{1,0,0,0,0,0,0,0,0,0,0,1,1,1,1,3,3,3,0,1},
{1,0,0,0,2,2,2,0,0,0,0,0,0,0,0,0,0,0,0,1},
{1,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,1},
{1,0,0,0,0,3,3,3,1,1,1,1,1,1,1,0,0,0,0,1},
{1,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,1},
{1,0,2,2,0,0,0,0,0,0,0,0,3,0,0,0,0,0,0,1},
{1,0,2,2,0,0,0,0,2,2,2,0,0,0,2,2,0,0,0,1},
{1,0,0,0,0,0,0,8,2,5,2,0,0,0,0,0,0,0,0,1},
{1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1}};
for(int x=0;x<20;x++)
{
for(int y=0;y<20;y++)
{
if(map[x][y]==2)
{
g.setColor(Color.red);
g.fillRect(100+x*20-9,50+y*20-4, 10, 5);
// g.drawLine(100+x*20-9,50+y*20-4,100+x*20+9,50+y*20-4);
// g.drawLine(100+x*20-9,50+y*20+4,100+x*20+9,50+y*20+4);
// g.drawLine(100+x*20-4,50+y*20-9,100+x*20-4,50+y*20+9);
// g.drawLine(100+x*20+4,50+y*20-9,100+x*20+4,50+y*20+9);
}
}
}
}
//定义一个函数,用于初始化敌人的坦克
private void init_EnemyTank()
{
//初始化敌人的坦克
for(int i=0;i<etSize;i++)
{
//创建一个敌人的坦克
EnemyTank et=new EnemyTank((i+1)*100+55,0);
//启动敌人的坦克线程,让敌人的坦克能够自由的移动
et.setDirection(2);//设置敌人坦克的初始化方向
Thread t=new Thread(et);
t.start();
//给敌人的坦克添加子弹
Shot EnemyShot=new Shot(et.x+40,et.y+30,2);
et.EnemyShots.add(EnemyShot);
Thread t2=new Thread(EnemyShot);
t2.start();
ets.add(et);//将敌人的坦克加入到Vector中
}
}
//定义一个函数,专门用于初始化游戏中加载的图片
private void init_img()
{
//初始化图片
try
{
image1=ImageIO.read(new File("image/bomb1.gif"));
image2=ImageIO.read(new File("image/bomb2.gif"));
image3=ImageIO.read(new File("image/bomb3.gif"));
//定义四个方向的坦克图片
tank_up=ImageIO.read(new File("image/tank_up.gif"));
tank_down=ImageIO.read(new File("image/tank_down.gif"));
tank_left=ImageIO.read(new File("image/tank_left.gif"));
tank_right=ImageIO.read(new File("image/tank_right.gif"));
zidan_img=ImageIO.read(new File("image/zidan1.gif"));
EnemyTank_up=ImageIO.read(new File("image/EnemyTank_up.gif"));
EnemyTank_down=ImageIO.read(new File("image/EnemyTank_down.gif"));
EnemyTank_left=ImageIO.read(new File("image/EnemyTank_left.gif"));
EnemyTank_right=ImageIO.read(new File("image/EnemyTank_right.gif"));
}
catch(Exception e)
{
}
}
//重新绘制
public void paint(Graphics g)
{
super.paint(g);
g.fillRect(0, 0, 800, 600);//设置活动区域
//画出我自己的坦克
if(hero.isLive)
{
this.drawTank(hero.getX(), hero.getY(), g,hero.getDirection());
}
init_map(g);//画出砖块
drawBomb(g);//画出zhadan
drawEnemyTank(g);//画出敌人的坦克(再画敌人坦克的同时,画出了敌人坦克的子弹)
drawMyShot(g);//画出我方坦克的子弹
}
//写一个函数,专门用于画出zhadan
private void drawBomb(Graphics g)
{
//画出zhadan
//循环遍历集合
for(int i=0;i<bombs.size();i++)
{
//取出 Bomb b=bombs.get(i);
if(b.bombLive>6)
{
g.drawImage(image1, b.x, b.y, 60, 60,this);
}
else if(b.bombLive>3)
{
g.drawImage(image2, b.x, b.y, 60, 60,this);
}
else
{
g.drawImage(image3, b.x, b.y, 60, 60,this);
}
//让的生命值减少
b.downLive();
//如果的生命值是0,就将从bombs中移除
bombs.remove(b);
}
}
//定义一个函数,用于专门画出敌人的坦克
private void drawEnemyTank(Graphics g)
{
//如果敌人的坦克存活着的话,就画出敌人的坦克
for(int i=0;i<ets.size();i++)
{
//取出敌人的坦克
EnemyTank et=ets.get(i);
if(et.isLive)
{
switch(et.direction)
{
case 0:
{
g.drawImage(EnemyTank_up, et.x, et.y, 60, 60,this);
break;
}
case 1:
{
g.drawImage(EnemyTank_right, et.x, et.y, 60, 60,this);
break;
}
case 2:
{
g.drawImage(EnemyTank_down, et.x, et.y, 60, 60,this);
break;
}
case 3:
{
g.drawImage(EnemyTank_left, et.x, et.y, 60, 60,this);
break;
}
}
drawEnemyShot(g, et);//顺便再画出敌人坦克的子弹
}
}
}
//定义一个函数,用于画出敌人坦克的子弹
private void drawEnemyShot(Graphics g, EnemyTank et)
{
//顺便再画出敌人坦克的子弹
for(int j=0;j<et.EnemyShots.size();j++)
{
//取出敌人的坦克的子弹
Shot s=et.EnemyShots.get(j);
if(s.isLive)//子弹存活,就画出子弹
{
switch(s.direction)
{
case 0:g.drawImage(zidan_img, s.x+15,s.y-180,10,10,this);break;
case 1:g.drawImage(zidan_img, s.x+55,s.y+25,10,10,this);break;
case 2:g.drawImage(zidan_img, s.x+75,s.y+10,10,10,this);break;
case 3:g.drawImage(zidan_img, s.x-5,s.y+25,10,10,this);break;
}
}
else
{
et.EnemyShots.remove(s);//如果子弹死亡,就将子弹从向量中移除
}
}
}
//专门定义一个函数用于画出我方坦克的子弹
private void drawMyShot(Graphics g)
{
//画出能够连发的子弹
//遍历存放子弹的容器s
for(int i=0;i<hero.ss.size();i++)
{
//取出我方坦克的所有子弹
Shot myShot=hero.ss.get(i);
if(myShot!=null&&myShot.isLive==true)//如果子弹没有死亡,并且子弹不为空,就画出子弹
{
switch(myShot.direction)
{
case 0:g.drawImage(zidan_img, myShot.x+15,myShot.y,10,10,this);break;
case 1:g.drawImage(zidan_img, myShot.x+25,myShot.y+25,10,10,this);break;
case 2:g.drawImage(zidan_img, myShot.x+15,myShot.y+35,10,10,this);break;
case 3:g.drawImage(zidan_img, myShot.x-5,myShot.y+25,10,10,this);break;
}
}
if(myShot.isLive==false)//如果子弹死亡了,就将子弹从容器中移除
{
ets.remove(myShot);
}
}
}
//定义一个画坦克的函数
public void drawTank(int x,int y,Graphics g,int direction)
{
//x:坦克的x坐标y:坦克的y坐标,g:画笔direction:确定坦克的方向,type:坦克的类型
//判断坦克的类型
//判断坦克的方向
switch(direction)
{
case 0:
{
g.drawImage(tank_up, x, y, 60, 60,this);
break;
}
case 1://坦克方向向右
{
g.drawImage(tank_right, x, y, 60, 60,this);
break;
}
case 2://坦克方向向下
{
g.drawImage(tank_down, x, y, 60, 60,this);
break;
}
case 3://坦克方向向左
{
g.drawImage(tank_left, x, y, 60, 60,this);
break;
}
}
}
//处理键盘按下事件
public void keyPressed(KeyEvent e)
{
//坦克向上移动
if(e.getKeyCode()==KeyEvent.VK_UP)
{
this.hero.setDirection(0);
this.hero.moveUP();
}
//坦克向右移动
else if(e.getKeyCode()==KeyEvent.VK_RIGHT)
{
this.hero.setDirection(1);
this.hero.moveRight();
}
//坦克向下移动
else if(e.getKeyCode()==KeyEvent.VK_DOWN)
{
this.hero.setDirection(2);
this.hero.moveDown();
}
//坦克向左移动
else if(e.getKeyCode()==KeyEvent.VK_LEFT)
{
this.hero.setDirection(3);
this.hero.moveLeft();
}
//判断玩家是否按下J键
if(e.getKeyCode()==KeyEvent.VK_SPACE)
{
this.hero.shotEnemy();//发射子弹
}
//必须重新绘制坦克,否则坦克不能动
this.repaint();
}
public void keyReleased(KeyEvent e)
{
}
public void keyTyped(KeyEvent e)
{
}
public void run()
{
while(true)
{
try
{
Thread.sleep(100);
} catch (InterruptedException e)
{
// TODO Auto-generated catch block
e.printStackTrace();
}
isShotEnemy();//判断我方坦克子弹是否集中敌人的坦克
isShotMe();//判断敌人坦克的子弹是否集中我方坦克
this.repaint();
}
}
//定义一个函数,用于判断敌人的坦克是否集中我方的坦克
private void isShotMe()
{
//随时判断敌人坦克的子弹是否几种我放的坦克
for(int i=0;i<ets.size();i++)
{
//取出所有的敌人的坦克
EnemyTank et=ets.get(i);
for(int j=0;j<et.EnemyShots.size();j++)
{
//取出敌人坦克的子弹
Shot s=et.EnemyShots.get(j);
isHitMe(s,hero);
}
}
}
//定义一个函数,用于判断我方的坦克是否集中敌人的坦克
private void isShotEnemy()
{
//随时判断子弹是否击中敌人的坦克
for(int i=0;i<hero.ss.size();i++)
{
//取出子弹
Shot s=hero.ss.get(i);
//首先判断子弹是否存活
if(s.isLive)
{
//循环遍历敌人的坦克
for(int j=0;j<ets.size();j++)
{
//取出敌人的坦克
EnemyTank et=ets.get(j);
//判断敌人的坦克是否还存活
if(et.isLive)
{
isHitTank(s,et);//调用子弹是否击中敌人坦克的标志
}
}
}
}
}
//定义一个函数专门判断子弹是否击中坦克(我方坦克和敌方坦克)
public void isHitTank(Shot s,Tank et)
{
//判断坦克的方向
switch(et.direction)
{
case 0:
case 2:
if(s.x>et.x&&s.x<et.x+64&&s.y>et.y&&s.y<et.y+79)
{
//子弹击中坦克
//子弹死亡
s.isLive=false;
//坦克死亡
et.isLive=false;
//创建一个子弹
Bomb b=new Bomb(et.x,et.y);
//将子弹加入到容器中
bombs.add(b);
}
break;
case 1:
case 3:
if(s.x>et.x&&s.x<et.x+79&&s.y>et.y&&s.y<et.y+64)
{
//子弹击中坦克
//子弹死亡
s.isLive=false;
//坦克死亡
et.isLive=false;
//创建一个子弹
Bomb b=new Bomb(et.x,et.y);
//将子弹加入到容器中
bombs.add(b);
}
break;
}
}
public void isHitMe(Shot s,Hero et)
{
//判断坦克的方向
switch(hero.direction)
{
case 0:
case 2:
if(s.x>et.x&&s.x<et.x+75&&s.y>et.y&&s.y<et.y+62)
{
//子弹击中坦克
//子弹死亡
s.isLive=false;
//坦克死亡
et.isLive=false;
//创建一个子弹
Bomb b=new Bomb(et.x,et.y);
//将子弹加入到容器中
bombs.add(b);
}
break;
case 1:
case 3:
if(s.x>et.x&&s.x<et.x+75&&s.y>et.y&&s.y<et.y+62)
{
//子弹击中坦克
//子弹死亡
s.isLive=false;
//坦克死亡
et.isLive=false;
//创建一个子弹
Bomb b=new Bomb(et.x,et.y);
//将子弹加入到容器中
bombs.add(b);
}
break;
}
}
}
package game;
import java.util.Vector;
/**
* 作者:郑云飞
* 内容:坦克大战项目实战
* 2010年8月20日画出坦克
* 2010年8月21日:让坦克动起来
* 2010年8月22日:让坦克发射子弹
* 2010年8月22日22:45分:让坦克能够连发子弹
* 2010年8月23日:让敌人的坦克能够自由移动和发射子弹
* 2010年8月24日:让敌人的坦克集中目标时,目标死亡
*
*/
//定义一个坦克类
class Tank
{
int x=0;//坦克的横坐标
int y=0;//坦克的纵坐标
int direction;//坦克的方向0:向上1:向右2:向下3:向左
int speed=3;//坦克的速度
boolean isLive=true;
//让坦克具有开火的功能
public int getSpeed()
{
return speed;
}
public void setSpeed(int speed)
{
this.speed = speed;
}
public int getDirection()
{
return direction;
}
public void setDirection(int direction)
{
this.direction = direction;
}
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 Hero extends Tank
{
public Hero(int x, int y,int direction)
{
super(x,y);
this.setSpeed(15);//设置自己坦克的速度
}
boolean isLive=true;
//让坦克具有开火的功能
Shot s=null;
//定义一个子弹数组
Vector<Shot> ss=new Vector<Shot>();
public void shotEnemy()
{
switch(this.direction)
{
case 0://坦克向上开火
{
s=new Shot(x+10,y-10,0);
ss.add(s);//将子弹放入容器中
break;
}
case 1://坦克向右开火
{
s=new Shot(x+30,y,1);
ss.add(s);
break;
}
case 2://坦克向下开火
{
s=new Shot(x+10,y+20,2);
ss.add(s);
break;
}
case 3://坦克向左开火
{
s=new Shot(x,y,3);
ss.add(s);
break;
}
}
//启动子弹线程
Thread t=new Thread(s);
t.start();
}
//坦克向上移动
public void moveUP()
{
if(y>0)
y-=speed;
}
//坦克向右移动
public void moveRight()
{
if(x<725)
x+=speed;
}
//坦克向下移动
public void moveDown()
{
if(y<510)
y+=speed;
}
//坦克向左移动
public void moveLeft()
{
if(x>0)
x-=speed;
}
}
//定义敌人的坦克数组
class EnemyTank extends Tank implements Runnable
{
int times=0;
public EnemyTank(int x, int y)
{
super(x,y);
this.setSpeed(1);//设置敌人坦克的速度
}
//定义一个向量用于存放敌人坦克的子弹
Vector<Shot> EnemyShots=new Vector<Shot>();
//敌人添加子弹应当在敌人坦克刚刚创建和敌人坦克的子弹死亡的时候
boolean flag=true;
public void run()
{
while(flag)
{
switch(this.direction)
{
case 0://敌人的坦克向上移动
{
for(int i=0;i<30;i++)
{
if(y>0)
{
y-=speed;
}
else
{
}
try
{
Thread.sleep(50);
}
catch(Exception e)
{
}
}
break;
}
case 1://敌人的坦克向右移动
{
for(int i=0;i<30;i++)
{
if(x<730)
{
x+=speed;
}
else
{
x=0;
}
try
{
Thread.sleep(50);
}
catch(Exception e)
{
}
}
break;
}
case 2://敌人的坦克向下移动
{
for(int i=0;i<30;i++)
{
if(y<530)
{
y+=speed;
}
try
{
Thread.sleep(50);
}
catch(Exception e)
{
}
}
break;
}
case 3://敌人的坦克向左的移动
{
for(int i =0;i<30;i++)
{
if(x>0)
{
x-=speed;
}
try
{
Thread.sleep(50);
}
catch(Exception e)
{
}
}
break;
}
}
//判断是否需要给敌人的坦克加入新的子弹
this.times++;
if(times%2==0)
{
if(isLive)//如果敌人的坦克还没有被击中
{
if(EnemyShots.size()<5)//如果敌人的坦克的子弹的数量小于5颗的话
{
Shot s=null;
switch(direction)
{
case 0:
{
//创建一个子弹
s=new Shot(x+10,y-20,0);
//把子弹加入到向量中
EnemyShots.add(s);
break;
}
case 1:
{
//创建一个子弹
s=new Shot(x,y,1);
//把子弹加入到向量中
EnemyShots.add(s);
break;
}
case 2:
{
//创建一个子弹
s=new Shot(x-50,y+50,2);
//把子弹加入到向量中
EnemyShots.add(s);
break;
}
case 3:
{
//创建一个子弹
s=new Shot(x,y,3);
//把子弹加入到向量中
EnemyShots.add(s);
break;
}
}
//启动子弹线程
Thread t=new Thread(s);
t.start();
}
}
}
//让坦克随机改变一个新的方向
this.direction=(int) (Math.random()*4);
//判断坦克是否死亡
if(this.isLive==false)
{
//让坦克退出线程
break;
}
}
}
}
//定义一个类
class Bomb
{
//定义的坐标
int x;
int y;
public Bomb(int x,int y)
{
this.x=x;
this.y=y;
}
//定义的生命(初始值为9)
int bombLive=9;
//是否存活的标志
boolean isLive=true;
//定义一个函数,让的生命自减
public void downLive()
{
if(bombLive>0)
{
bombLive--;
}
else
{
this.isLive=false;//生命死亡
}
}
}
//定义子弹类
class Shot implements Runnable
{
//定义子弹的坐标
int x;
int y;
int direction;//子弹的方向
int speed=3;//子弹的速度
boolean isLive=true;//判断子弹是否存活的标志
//构造函数
public Shot(int x, int y,int direction)
{
this.x=x;
this.y=y;
this.direction=direction;
}
public void run()
{
while(true)
{
//根据坦克的方向反射子弹
try
{
Thread.sleep(50);//让线程睡眠50毫秒,否则太快看不到效果
}
catch(Exception e)
{
}
switch(direction)
{
case 0://子弹向上发射
{
y-=speed;
break;
}
case 1://子弹向右发射
{
x+=speed;
break;
}
case 2://子弹向下发射
{
y+=speed;
break;
}
case 3://子弹向左发射
{
x-=speed;
break;
}
}
//子弹碰到墙壁时
if(x<0||x>800||y<0||y>600)
{
this.isLive=false;//标志子弹生命死亡
break;
}
}
}
}