首先创建一个包,在包中写4个类,GamePanel是绘图面板,Hero是己方坦克,敌方坦克和己方坦克都都坦克,所以可以写一个父类Tank,TankGames是main函数运行的地方
Tank:
public class Tank {
//坦克的坐标(x,y)
private int x;
private int y;
public Tank(int x, int y) {
this.x = x;
this.y = y;
}
public int getX() {
return x;
}
public int getY() {
return y;
}
}
Hero:
public class Hero extends Tank{
public Hero(int x, int y) {
super(x, y);
}
}
GamePanel:Panel类似画板,而Graphics就是一支画笔
paint方法触发机制:
① 第一次在屏幕显示时,系统自动调用 ② 窗口大小变化(最小化/最大化) ③ repaint方法被调用
public class GamePanel extends JPanel {
//在面板上定义己方的坦克Hero
Hero hero=null;
public GamePanel() {
hero= new Hero(100,100);//设置己方坦克的坐标
}
//用画笔开始画
public void paint(Graphics g){
//将g设置为画笔
super.paint(g);
//填充矩形 fillRect(int x,int y,int width,int height)
g.fillRect(0,0,1000,750);
}
}
TankGames:Frame类似画框
public class TankGames extends JFrame {
public static void main(String[] args) {
TankGames tankGames = new TankGames();
}
//定义面板
GamePanel gamePanel=null;
public TankGames(){
gamePanel=new GamePanel();
this.add(gamePanel);//将面板添加在画框上
this.setSize(1000,750);//设置画框高和宽
this.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);//按下x就退出程序
this.setVisible(true);//画框可视
}
}
效果如图:
一个向上的坦克坐标如图:
绘制坦克在GamePanel类中绘制
public class GamePanel extends JPanel {
//在面板上定义自己的坦克Hero
Hero hero=null;
public GamePanel() {
hero= new Hero(100,100);//设置自己坦克的坐标
}
//用画笔开始画
public void paint(Graphics g){
//将g设置为画笔
super.paint(g);
//填充矩形 fillRect(int x,int y,int width,int height)
g.fillRect(0,0,1000,750);
drawTank(hero.getX(),hero.getY(),g,0,0 );
}
public void drawTank(int x,int y,Graphics g,int type,int direction){
switch (type){
case 0:
g.setColor(Color.blue);
break;
case 1:
g.setColor(Color.red);
break;
}
switch (direction){
case 0:
g.fill3DRect(x,y,10,60,false);//画出左轮子
g.fill3DRect(x+10,y+10,20,40,false);//画出右轮子
g.fill3DRect(x+30,y,10,60,false);//画出身体
g.fillOval(x + 10, y + 20, 20, 20);//画出圆形炮台
g.drawLine(x+20,y,x+20,y+20);//画出炮筒
break;
case 1:
g.fill3DRect(x,y,60,10,false);//画出左轮子
g.fill3DRect(x+10,y+10,40,20,false);//画出右轮子
g.fill3DRect(x,y+30,60,10,false);//画出身体
g.fillOval(x + 20, y + 10, 20, 20);//画出圆形炮台
g.drawLine(x+40,y+20,x+60,y+20);//画出炮筒
break;
case 2:
g.fill3DRect(x,y,10,60,false);//画出左轮子
g.fill3DRect(x+10,y+10,20,40,false);//画出右轮子
g.fill3DRect(x+30,y,10,60,false);//画出身体
g.fillOval(x + 10, y + 20, 20, 20);//画出圆形炮台
g.drawLine(x+20,y+40,x+20,y+60);//画出炮筒
break;
case 3:
g.fill3DRect(x,y,60,10,false);//画出左轮子
g.fill3DRect(x+10,y+10,40,20,false);//画出右轮子
g.fill3DRect(x,y+30,60,10,false);//画出身体
g.fillOval(x + 20, y + 10, 20, 20);//画出圆形炮台
g.drawLine(x,y+20,x+20,y+20);//画出炮筒
break;
}
}
}
效果如图
让坦克动起来需要添加键盘的操作,也就是添加监听事件
首先需要在TankGames的构造器中让JFrame监听gamePanel(画板)的键盘事件
public class TankGames extends JFrame {
//定义面板
GamePanel gamePanel=null;
public static void main(String[] args) {
TankGames tankGames = new TankGames();
}
public TankGames(){
gamePanel=new GamePanel();
this.add(gamePanel);//将面板添加在画框上
this.setSize(1000,750);//设置画框高和宽
this.addKeyListener(gamePanel);//给面板增添监听事件,让JFrame监听gamePanel的键盘事件
this.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);//按下x就退出程序
this.setVisible(true);
}
}
由于坦克的运动是由速度speed和方向direction决定的,所以可以在Tank中定义速度speed和方向direction属性,并设置默认速度=1以及默认方向=0(向上),用set(),get()方法设置当前速度/方向获取当前速度/方向。
public class Tank {
//坦克的坐标(x,y)
private int x;
private int y;
private int direction=0;//默认方向为向上
private int speed=1;//默认速度为1
public Tank(int x, int y) {
this.x = x;
this.y = y;
}
public int getX() {
return x;
}
public int getY() {
return y;
}
public int getDirection() {
return direction;
}
public void setDirection(int direction) {
this.direction = direction;
}
public int getSpeed() {
return speed;
}
public void setSpeed(int speed) {
this.speed = speed;
}
//向上走
public void makeUp(){
y=y-speed;
}
//向右走
public void makeRight(){
x=x+speed;
}
//向下走
public void makeDown(){
y=y+speed;
}
//向左走
public void makeLeft(){
x=x-speed;
}
}
增加面板的键盘监听就需要在类声明时继承KeyListener,继承后重写keyTyped() keyPressed() keyReleased(),而控制坦克的移动只需要按下PressedWDSA即可,所以只需要写keyPressed() 方法的内容。
在keyPressed() 方法中,当按下W坦克更换方向 hero.setDirection(0)+向上走一步hero.makeUp()其他的按键以此类推,需要注意的是每次更改完坦克的运行状态时都需要调用repain()方法重新绘制面板
GamePanel:
public class GamePanel extends JPanel implements KeyListener {
//在面板上定义自己的坦克Hero
Hero hero=null;
public GamePanel() {
hero= new Hero(100,100);//设置自己坦克的坐标
}
//用画笔开始画
public void paint(Graphics g){
//将g设置为画笔
super.paint(g);
//填充矩形 fillRect(int x,int y,int width,int height)
g.fillRect(0,0,1000,750);
drawTank(hero.getX(),hero.getY(),g,0,hero.getDirection());
}
public void drawTank(int x,int y,Graphics g,int type,int direction){
switch (type){
case 0:
g.setColor(Color.blue);
break;
case 1:
g.setColor(Color.red);
break;
}
switch (direction){
case 0:
g.fill3DRect(x,y,10,60,false);//画出左轮子
g.fill3DRect(x+10,y+10,20,40,false);//画出右轮子
g.fill3DRect(x+30,y,10,60,false);//画出身体
g.fillOval(x + 10, y + 20, 20, 20);//画出圆形炮台
g.drawLine(x+20,y,x+20,y+20);//画出炮筒
break;
case 1:
g.fill3DRect(x,y,60,10,false);//画出左轮子
g.fill3DRect(x+10,y+10,40,20,false);//画出右轮子
g.fill3DRect(x,y+30,60,10,false);//画出身体
g.fillOval(x + 20, y + 10, 20, 20);//画出圆形炮台
g.drawLine(x+40,y+20,x+60,y+20);//画出炮筒
break;
case 2:
g.fill3DRect(x,y,10,60,false);//画出左轮子
g.fill3DRect(x+10,y+10,20,40,false);//画出右轮子
g.fill3DRect(x+30,y,10,60,false);//画出身体
g.fillOval(x + 10, y + 20, 20, 20);//画出圆形炮台
g.drawLine(x+20,y+40,x+20,y+60);//画出炮筒
break;
case 3:
g.fill3DRect(x,y,60,10,false);//画出左轮子
g.fill3DRect(x+10,y+10,40,20,false);//画出右轮子
g.fill3DRect(x,y+30,60,10,false);//画出身体
g.fillOval(x + 20, y + 10, 20, 20);//画出圆形炮台
g.drawLine(x,y+20,x+20,y+20);//画出炮筒
break;
}
}
@Override
public void keyTyped(KeyEvent e) {
}
@Override
public void keyPressed(KeyEvent e) {
if(e.getKeyCode()==KeyEvent.VK_W){ //若键盘按下w
//坦克改变方向
hero.setDirection(0);
//坦克向上走1步
hero.makeUp();
}else if(e.getKeyCode()==KeyEvent.VK_D){//若键盘按下D
hero.setDirection(1);
hero.makeRight();
}else if(e.getKeyCode()==KeyEvent.VK_S) {//若键盘按下S
hero.setDirection(2);
hero.makeDown();
}else if(e.getKeyCode()==KeyEvent.VK_A){//若键盘按下A
hero.setDirection(3);
hero.makeLeft();
}
//重新绘制图像
this.repaint();
}
@Override
public void keyReleased(KeyEvent e) {
}
}
绘制敌人坦克
在绘制敌人坦克之前需要添加一个Enemy类添加敌人坦克一些属性如多线程,以区分己方坦克
public class Enemy extends Tank {
public Enemy(int x, int y) {
super(x, y);
}
}
绘制敌人坦克就需要在GamePanel中绘制,由于敌人有多个而且是多线程的,这样就可以定义Vector容器将敌人放入其中
public class GamePanel extends JPanel implements KeyListener {
//在面板上定义自己的坦克Hero
Hero hero=null;
//在面板上用vector定义敌人坦克
Vector enemyTank=new Vector<>();
//设置敌人的坦克个数为3
int enemyTankSize=3;
public GamePanel() {
hero= new Hero(100,100);//设置自己坦克的坐标
//for循环设置敌人的坦克
for(int i=0;i
Enemy enemy=new Enemy(100*(i+1),0);//第一个坦克的坐标为(100,0),第二个为(200,0)以此类推
enemy.setDirection(2);//设置坦克的方向向下(向下攻击己方坦克)
enemyTank.add(enemy);
}
}
//用画笔开始画
public void paint(Graphics g){
//将g设置为画笔
super.paint(g);
//填充矩形 fillRect(int x,int y,int width,int height)
g.fillRect(0,0,1000,750);
drawTank(hero.getX(),hero.getY(),g,0,hero.getDirection());
for(int i=0;i
drawTank(enemyTank.get(i).getX(),enemyTank.get(i).getY(),g,1,enemyTank.get(i).getDirection());
}
}
public void drawTank(int x,int y,Graphics g,int type,int direction){
switch (type){
case 0:
g.setColor(Color.blue);
break;
case 1:
g.setColor(Color.red);
break;
}
switch (direction){
case 0:
g.fill3DRect(x,y,10,60,false);//画出左轮子
g.fill3DRect(x+10,y+10,20,40,false);//画出右轮子
g.fill3DRect(x+30,y,10,60,false);//画出身体
g.fillOval(x + 10, y + 20, 20, 20);//画出圆形炮台
g.drawLine(x+20,y,x+20,y+20);//画出炮筒
break;
case 1:
g.fill3DRect(x,y,60,10,false);//画出左轮子
g.fill3DRect(x+10,y+10,40,20,false);//画出右轮子
g.fill3DRect(x,y+30,60,10,false);//画出身体
g.fillOval(x + 20, y + 10, 20, 20);//画出圆形炮台
g.drawLine(x+40,y+20,x+60,y+20);//画出炮筒
break;
case 2:
g.fill3DRect(x,y,10,60,false);//画出左轮子
g.fill3DRect(x+10,y+10,20,40,false);//画出右轮子
g.fill3DRect(x+30,y,10,60,false);//画出身体
g.fillOval(x + 10, y + 20, 20, 20);//画出圆形炮台
g.drawLine(x+20,y+40,x+20,y+60);//画出炮筒
break;
case 3:
g.fill3DRect(x,y,60,10,false);//画出左轮子
g.fill3DRect(x+10,y+10,40,20,false);//画出右轮子
g.fill3DRect(x,y+30,60,10,false);//画出身体
g.fillOval(x + 20, y + 10, 20, 20);//画出圆形炮台
g.drawLine(x,y+20,x+20,y+20);//画出炮筒
break;
}
}
@Override
public void keyTyped(KeyEvent e) {
}
@Override
public void keyPressed(KeyEvent e) {
if(e.getKeyCode()==KeyEvent.VK_W){ //若接受到键盘按下w
//坦克改变方向
hero.setDirection(0);
//坦克向上走1步
hero.makeUp();
}else if(e.getKeyCode()==KeyEvent.VK_D){
hero.setDirection(1);
hero.makeRight();
}else if(e.getKeyCode()==KeyEvent.VK_S) {
hero.setDirection(2);
hero.makeDown();
}else if(e.getKeyCode()==KeyEvent.VK_A){
hero.setDirection(3);
hero.makeLeft();
}
//重新绘制图像
this.repaint();
}
@Override
public void keyReleased(KeyEvent e) {
}
}
效果如图
我们可以按下J让自己的坦克对敌人坦克发动攻击,如果设计子弹那么可以写一个Shot类,Shot类中有子弹的坐标(x,y),方向,是否存活等属性,坦克每按下J就发射一个子弹其实子弹相当于一个线程,每按下J,hero就创建一个子弹的线程并启动,启动后根据子弹的当前的位置让子弹以速度speed=2朝坦克炮筒前方运动,子弹运动终止条件为:① 碰到游戏区域边界 ② 碰到敌人坦克
Shot:
public class Shot implements Runnable{
private int x;
private int y;
private int direction;
private int speed=2;//默认速度为2
private boolean isLive=true;//一旦创建了子弹,那么子弹就是存活的
public Shot(int x, int y, int direction) {
this.x = x;
this.y = y;
this.direction = direction;
}
public boolean isLive() {
return isLive;
}
public int getX() {
return x;
}
public int getY() {
return y;
}
@Override
public void run() {
while(isLive){
try {
Thread.sleep(50);//子弹休眠50毫秒
} catch (InterruptedException e) {
e.printStackTrace();
}
switch (direction){
case 0:
y=y-speed;
break;
case 1:
x=x+speed;
break;
case 2:
y=y+speed;
break;
case 3:
x=x-speed;
break;
}
if(x<=0||x>=1000||y<=0||y>=750){
isLive=false;
}
}
}
}
Hero:这里要注意子弹设置的位置
public class Hero extends Tank{
//创建子弹
private Shot shot=null;
public Shot getShot() {
return shot;
}
public Hero(int x, int y) {
super(x, y);
}
//射击
public void shotEnemy(){
switch (getDirection()){
case 0://hero向上
shot=new Shot(getX()+20,getY(),0);
break;
case 1:
shot=new Shot(getX()+60,getY()+20,1);
break;
case 2:
shot=new Shot(getX()+20,getY()+60,2);
break;
case 3:
shot=new Shot(getX(),getY()+20,3);
break;
}
new Thread(shot).start();//启动子弹线程
}
}
在绘制子弹时,如果仿照绘制坦克上下左右移动的代码,如果按下J增加一个键盘监听事件并调用一次this.repaint()重新绘制图像就会出现子弹只显示一次后就再也没有出现的问题,面对这种情况可以将GamePanel类设计成一个线程,在main函数中启动,重写的run()方法中进行不停的绘制图像。
GamePanel:
public class GamePanel extends JPanel implements KeyListener,Runnable{
//在面板上定义自己的坦克Hero
Hero hero=null;
//在面板上用vector定义敌人坦克
Vector enemyTank=new Vector<>();
//设置敌人的坦克个数为3
int enemyTankSize=3;
public GamePanel() {
hero= new Hero(100,100);//设置自己坦克的坐标
hero.setSpeed(3);
//for循环设置敌人的坦克
for(int i=0;i
Enemy enemy=new Enemy(100*(i+1),0);//第一个坦克的坐标为(100,0),第二个为(200,0)以此类推
enemy.setDirection(2);//设置坦克的方向向下(向下攻击己方坦克)
enemyTank.add(enemy);
}
}
//用画笔开始画
public void paint(Graphics g){
super.paint(g);//将g设置为画笔
// 填充矩形 fillRect(int x,int y,int width,int height)
g.fillRect(0,0,1000,750);
drawTank(hero.getX(),hero.getY(),g,0,hero.getDirection());
//如果子弹被创建或者子弹还存在就绘制子弹的图
if(hero.getShot()!=null&&hero.getShot().isLive()){
drawShot(hero.getX(),hero.getY(),g);
}
for(int i=0;i
drawTank(enemyTank.get(i).getX(),enemyTank.get(i).getY(),g,1,enemyTank.get(i).getDirection());
}
}
public void drawTank(int x,int y,Graphics g,int type,int direction){
switch (type){
case 0:
g.setColor(Color.blue);
break;
case 1:
g.setColor(Color.red);
break;
}
switch (direction){
case 0:
g.fill3DRect(x,y,10,60,false);//画出左轮子
g.fill3DRect(x+10,y+10,20,40,false);//画出右轮子
g.fill3DRect(x+30,y,10,60,false);//画出身体
g.fillOval(x + 10, y + 20, 20, 20);//画出圆形炮台
g.drawLine(x+20,y,x+20,y+20);//画出炮筒
break;
case 1:
g.fill3DRect(x,y,60,10,false);//画出左轮子
g.fill3DRect(x+10,y+10,40,20,false);//画出右轮子
g.fill3DRect(x,y+30,60,10,false);//画出身体
g.fillOval(x + 20, y + 10, 20, 20);//画出圆形炮台
g.drawLine(x+40,y+20,x+60,y+20);//画出炮筒
break;
case 2:
g.fill3DRect(x,y,10,60,false);//画出左轮子
g.fill3DRect(x+10,y+10,20,40,false);//画出右轮子
g.fill3DRect(x+30,y,10,60,false);//画出身体
g.fillOval(x + 10, y + 20, 20, 20);//画出圆形炮台
g.drawLine(x+20,y+40,x+20,y+60);//画出炮筒
break;
case 3:
g.fill3DRect(x,y,60,10,false);//画出左轮子
g.fill3DRect(x+10,y+10,40,20,false);//画出右轮子
g.fill3DRect(x,y+30,60,10,false);//画出身体
g.fillOval(x + 20, y + 10, 20, 20);//画出圆形炮台
g.drawLine(x,y+20,x+20,y+20);//画出炮筒
break;
}
}
public void drawShot(int x,int y,Graphics g){
g.setColor(Color.white);
g.draw3DRect(hero.getShot().getX(),hero.getShot().getY(),2,2,false);
}
@Override
public void keyTyped(KeyEvent e) {
}
@Override
public void keyPressed(KeyEvent e) {
if(e.getKeyCode()==KeyEvent.VK_W) { //若接受到键盘按下w
//坦克改变方向
hero.setDirection(0);
//坦克向上走1步
hero.makeUp();
}
if(e.getKeyCode()==KeyEvent.VK_D) {
hero.setDirection(1);
hero.makeRight();
}
if(e.getKeyCode()==KeyEvent.VK_S) {
hero.setDirection(2);
hero.makeDown();
}
if(e.getKeyCode()==KeyEvent.VK_A){
hero.setDirection(3);
hero.makeLeft();
}
if(e.getKeyCode()==KeyEvent.VK_J){
hero.shotEnemy();
}
//重新绘制图像
this.repaint();
}
@Override
public void keyReleased(KeyEvent e) {
}
@Override
public void run(){
while (true){
try {
Thread.sleep(100);//子弹每隔0.5s重新绘制图像
} catch (InterruptedException e) {
e.printStackTrace();
}
this.repaint();
}
}
}
main:
public class TankGames extends JFrame {
//定义面板
GamePanel gamePanel=null;
public static void main(String[] args) {
TankGames tankGames = new TankGames();
}
public TankGames(){
gamePanel=new GamePanel();
new Thread(gamePanel).start();
this.add(gamePanel);//将面板添加在画框上
this.setSize(1000,750);//设置画框高和宽
this.addKeyListener(gamePanel);//给面板增添监听事件
this.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);//按下x就退出程序
this.setVisible(true);
}
}
敌人发动攻击
敌人发动攻击的子弹生命周期是从创建敌人坦克开始,创建好敌人各自的子弹后并启动子弹的线程,注意敌人各自的子弹创建后要放在一个Vector容器中,以方便后序的操作。
Enemy:
public class Enemy extends Tank {
public Vector shots=new Vector<>();//vector容器中存放敌人的子弹
public Enemy(int x, int y) {
super(x, y);
}
}
GamePanel:
public class GamePanel extends JPanel implements KeyListener,Runnable{
//在面板上定义自己的坦克Hero
Hero hero=null;
//在面板上用vector定义敌人坦克
Vector enemyTank=new Vector<>();
//设置敌人的坦克个数为3
int enemyTankSize=3;
public GamePanel() {
hero= new Hero(100,100);//设置hero坦克的坐标
hero.setSpeed(3);//设置hero的速度
//for循环设置敌人的坦克
for(int i=0;i
Enemy enemy=new Enemy(100*(i+1),0);//第一个坦克的坐标为(100,0),第二个为(200,0)以此类推
enemy.setDirection(2);//设置坦克的方向向下(向下攻击己方坦克)
enemyTank.add(enemy);//在vector中添加当前创建的坦克
Shot shot=new Shot(enemy.getX()+20,enemy.getY()+60,2);//创建当前敌人的子弹
enemy.shots.add(shot);//将子弹添加在敌人类的vector容器中
new Thread(shot).start();//启动当前子弹进程
}
}
//用画笔开始画
public void paint(Graphics g){
super.paint(g);//将g设置为画笔
// 填充矩形 fillRect(int x,int y,int width,int height)
g.fillRect(0,0,1000,750);
drawTank(hero.getX(),hero.getY(),g,0,hero.getDirection());
//如果子弹被创建或者子弹还存在就绘制子弹的图
if(hero.getShot()!=null&&hero.getShot().isLive()){
drawHeroShot(hero.getX(),hero.getY(),g);
}
for(int i=0;i
//取出一个敌人
Enemy enemy=enemyTank.get(i);
//绘制取出的这个敌人
drawTank(enemy.getX(),enemy.getY(),g,1,enemy.getDirection());
//绘制当前敌人的子弹
for(int j=0;j
Shot shot=enemy.shots.get(j);//取出当前敌人的子弹
//如果shot存在,就绘制子弹;如果shot不存在,那么就从vector中移除子弹
if(shot.isLive()==true){
//绘制敌人子弹
g.setColor(Color.white);
g.draw3DRect(shot.getX(),shot.getY(),2,2,false);
}
else{
enemy.shots.remove(shot);//将shot从shots中移除
}
}
}
}
public void drawTank(int x,int y,Graphics g,int type,int direction){
switch (type){
case 0:
g.setColor(Color.blue);
break;
case 1:
g.setColor(Color.red);
break;
}
switch (direction){
case 0:
g.fill3DRect(x,y,10,60,false);//画出左轮子
g.fill3DRect(x+10,y+10,20,40,false);//画出右轮子
g.fill3DRect(x+30,y,10,60,false);//画出身体
g.fillOval(x + 10, y + 20, 20, 20);//画出圆形炮台
g.drawLine(x+20,y,x+20,y+20);//画出炮筒
break;
case 1:
g.fill3DRect(x,y,60,10,false);//画出左轮子
g.fill3DRect(x+10,y+10,40,20,false);//画出右轮子
g.fill3DRect(x,y+30,60,10,false);//画出身体
g.fillOval(x + 20, y + 10, 20, 20);//画出圆形炮台
g.drawLine(x+40,y+20,x+60,y+20);//画出炮筒
break;
case 2:
g.fill3DRect(x,y,10,60,false);//画出左轮子
g.fill3DRect(x+10,y+10,20,40,false);//画出右轮子
g.fill3DRect(x+30,y,10,60,false);//画出身体
g.fillOval(x + 10, y + 20, 20, 20);//画出圆形炮台
g.drawLine(x+20,y+40,x+20,y+60);//画出炮筒
break;
case 3:
g.fill3DRect(x,y,60,10,false);//画出左轮子
g.fill3DRect(x+10,y+10,40,20,false);//画出右轮子
g.fill3DRect(x,y+30,60,10,false);//画出身体
g.fillOval(x + 20, y + 10, 20, 20);//画出圆形炮台
g.drawLine(x,y+20,x+20,y+20);//画出炮筒
break;
}
}
public void drawHeroShot(int x, int y, Graphics g){
g.setColor(Color.white);
g.draw3DRect(hero.getShot().getX(),hero.getShot().getY(),2,2,false);
}
@Override
public void keyTyped(KeyEvent e) {
}
@Override
public void keyPressed(KeyEvent e) {
if(e.getKeyCode()==KeyEvent.VK_W) { //若接受到键盘按下w
//坦克改变方向
hero.setDirection(0);
//坦克向上走1步
hero.makeUp();
}
if(e.getKeyCode()==KeyEvent.VK_D) {
hero.setDirection(1);
hero.makeRight();
}
if(e.getKeyCode()==KeyEvent.VK_S) {
hero.setDirection(2);
hero.makeDown();
}
if(e.getKeyCode()==KeyEvent.VK_A){
hero.setDirection(3);
hero.makeLeft();
}
if(e.getKeyCode()==KeyEvent.VK_J){
hero.shotEnemy();
}
//重新绘制图像
this.repaint();
}
@Override
public void keyReleased(KeyEvent e) {
}
@Override
public void run(){
while (true){
try {
Thread.sleep(100);//子弹每隔0.5s重新绘制图像
} catch (InterruptedException e) {
e.printStackTrace();
}
this.repaint();
}
}
}
坦克攻击敌人的爆炸效果
爆炸效果是贴图完成的,三张从爆炸从大到小的图片快速切换会出现爆炸的效果,如图:
因此爆炸的本质是图片的切换,图片需要坐标(x,y),切换时间(生命周期),因此可以将其写成一个爆炸Bomb类,还需要写一个生命周期递减函数,给爆炸赋予“时间”。
public class Bomb {
private int x;
private int y;
private boolean isLive=true;//是否存在
private int lifeCycle=9;//生命周期
public Bomb(int x, int y) {
this.x = x;
this.y = y;
}
public int getX() {
return x;
}
public int getY() {
return y;
}
public int getLifeCycle() {
return lifeCycle;
}
public boolean isLive() {
return isLive;
}
public void lifeCycleDown(){
//生命周期递减
if(lifeCycle>0)
lifeCycle--;
else //若生命周期为0则爆炸效果销毁
isLive=false;
}
}
在Hero攻击敌人坦克,若攻击到敌人坦克绘制范围内,那么敌人坦克此时应该从Vectoer容器中移除,为了记录当前坦克销毁,在Enemy类中添加是否存活的属性
Enemy:
public class Enemy extends Tank {
public Vector shots=new Vector<>();//vector容器中存放敌人的子弹
private boolean isLive=true;//敌人坦克是否存活
public Enemy(int x, int y) {
super(x, y);
}
public boolean isLive() {
return isLive;
}
public void setLive(boolean live) {
isLive = live;
}
}
在绘制爆炸效果中,需要定义三张图片并加载到项目中,还需要定义爆炸的vector容器,当hero击中敌人的坦克就创建一个爆炸Bomb放入该容器中,当爆炸生命周期结束时将Bomb移除(remove)后还需要将Enemy本身从vector中移除(remove)。
在游戏过程中,程序需要一直处于“监视”状态来判断敌人坦克是否被击中,所以判断击中函数最好放在线程中每隔100毫秒来判断敌人坦克是否被击中。
GamePanel :
public class GamePanel extends JPanel implements KeyListener,Runnable{
//在面板上定义自己的坦克Hero
Hero hero=null;
//在面板上用vector定义敌人坦克
Vector enemyTank=new Vector<>();
//设置敌人的坦克个数为3
int enemyTankSize=3;
//用vector定义爆炸
Vector bombs=new Vector<>();
//定义爆炸效果图片
Image[] images=new Image[3];
public GamePanel() {
//设置hero
hero= new Hero(100,100);//设置hero坦克的坐标
hero.setSpeed(3);//设置hero的速度
//for循环设置敌人的坦克
for(int i=0;i
Enemy enemy=new Enemy(100*(i+1),0);//第一个坦克的坐标为(100,0),第二个为(200,0)以此类推
enemy.setDirection(2);//设置坦克的方向向下(向下攻击己方坦克)
enemyTank.add(enemy);//在vector中添加当前创建的坦克
Shot shot=new Shot(enemy.getX()+20,enemy.getY()+60,2);//创建当前敌人的子弹
enemy.shots.add(shot);//将子弹添加在敌人类的vector容器中
new Thread(shot).start();//启动当前子弹进程
}
//设置图片
images[0]=Toolkit.getDefaultToolkit().getImage("D:\java-code\JavaCode\src\TankGames\bomb_1.gif");
images[1]=Toolkit.getDefaultToolkit().getImage("D:\java-code\JavaCode\src\TankGames\bomb_2.gif");
images[2]=Toolkit.getDefaultToolkit().getImage("D:\java-code\JavaCode\src\TankGames\bomb_3.gif");
}
//用画笔开始画
public void paint(Graphics g){
super.paint(g);//将g设置为画笔
// 填充矩形 fillRect(int x,int y,int width,int height)
g.fillRect(0,0,1000,750);
//绘制hero坦克
drawTank(hero.getX(),hero.getY(),g,0,hero.getDirection());
//如果子弹被创建或者子弹还存在就绘制子弹的图
if(hero.getShot()!=null&&hero.getShot().isLive()){
drawHeroShot(hero.getX(),hero.getY(),g);
}
//绘制敌人坦克
for(int i=0;i
//取出一个敌人
Enemy enemy=enemyTank.get(i);
//判断当前敌人坦克是否存活
if(enemy.isLive()==true){
//绘制取出的这个敌人
drawTank(enemy.getX(),enemy.getY(),g,1,enemy.getDirection());
//绘制当前敌人的子弹
for(int j=0;j
Shot shot=enemy.shots.get(j);//取出当前敌人的子弹
//如果shot存在,就绘制子弹;如果shot不存在,那么就从vector中移除子弹
if(shot.isLive()==true){
//绘制敌人子弹
g.setColor(Color.white);
g.draw3DRect(shot.getX(),shot.getY(),2,2,false);
}
else{
enemy.shots.remove(shot);//将shot从shots中移除
}
}
}
}
//绘制爆炸效果
for(int i=0;i
Bomb bomb=bombs.get(i);
if(bomb.getLifeCycle()>6){
}else if(bomb.getLifeCycle()>3){
g.drawImage(images[1],bomb.getX(),bomb.getY(),60,60,this);
}else
g.drawImage(images[2],bomb.getX(),bomb.getY(),60,60,this);
bomb.lifeCycleDown();//让爆炸生命周期减小
if(bomb.getLifeCycle()==0)//若爆炸的生命周期为0就将当前bomb从vector中移除
bombs.remove(bomb);
}
}
public void drawTank(int x,int y,Graphics g,int type,int direction){
switch (type){
case 0:
g.setColor(Color.blue);
break;
case 1:
g.setColor(Color.red);
break;
}
switch (direction){
case 0:
g.fill3DRect(x,y,10,60,false);//画出左轮子
g.fill3DRect(x+10,y+10,20,40,false);//画出右轮子
g.fill3DRect(x+30,y,10,60,false);//画出身体
g.fillOval(x + 10, y + 20, 20, 20);//画出圆形炮台
g.drawLine(x+20,y,x+20,y+20);//画出炮筒
break;
case 1:
g.fill3DRect(x,y,60,10,false);//画出左轮子
g.fill3DRect(x+10,y+10,40,20,false);//画出右轮子
g.fill3DRect(x,y+30,60,10,false);//画出身体
g.fillOval(x + 20, y + 10, 20, 20);//画出圆形炮台
g.drawLine(x+40,y+20,x+60,y+20);//画出炮筒
break;
case 2:
g.fill3DRect(x,y,10,60,false);//画出左轮子
g.fill3DRect(x+10,y+10,20,40,false);//画出右轮子
g.fill3DRect(x+30,y,10,60,false);//画出身体
g.fillOval(x + 10, y + 20, 20, 20);//画出圆形炮台
g.drawLine(x+20,y+40,x+20,y+60);//画出炮筒
break;
case 3:
g.fill3DRect(x,y,60,10,false);//画出左轮子
g.fill3DRect(x+10,y+10,40,20,false);//画出右轮子
g.fill3DRect(x,y+30,60,10,false);//画出身体
g.fillOval(x + 20, y + 10, 20, 20);//画出圆形炮台
g.drawLine(x,y+20,x+20,y+20);//画出炮筒
break;
}
}
public void drawHeroShot(int x, int y, Graphics g){
g.setColor(Color.white);
g.draw3DRect(hero.getShot().getX(),hero.getShot().getY(),2,2,false);
}
//hero坦克击中敌人坦克
public void hitEnemy(Shot shot,Enemy enemy){
switch (enemy.getDirection())
{
//如果敌人坦克方向向上/向下(0/2),hero坦克击中
case 0:
case 2:
//hero子弹在当前敌人坦克的区域
if(shot.getX()<=enemy.getX()+40 && shot.getX()>=enemy.getX() && shot.getY()>=enemy.getY() && shot.getY()<=enemy.getY()+60){
shot.setLive(false);//hero子弹销毁
enemy.setLive(false);//敌人销毁
//敌人销毁后爆炸效果创建
Bomb bomb=new Bomb(enemy.getX(),enemy.getY());//创建爆炸效果
bombs.add(bomb);//将爆炸效果添加在vector中
enemyTank.remove(enemy);
}
break;
case 1:
case 3:
if(shot.getX()<=enemy.getX()+60&&shot.getX()>=enemy.getX()&& shot.getY()>=enemy.getY() && shot.getY()<=enemy.getY()+40){
shot.setLive(false);//hero子弹销毁
enemy.setLive(false);//敌人销毁
//敌人销毁后爆炸效果创建
Bomb bomb=new Bomb(enemy.getX(),enemy.getY());//创建爆炸效果
bombs.add(bomb);//将爆炸效果添加在vector中
enemyTank.remove(enemy);
}
break;
}
}
@Override
public void keyTyped(KeyEvent e) {
}
@Override
public void keyPressed(KeyEvent e) {
if(e.getKeyCode()==KeyEvent.VK_W) { //若接受到键盘按下w
//坦克改变方向
hero.setDirection(0);
//坦克向上走1步
hero.makeUp();
}
if(e.getKeyCode()==KeyEvent.VK_D) {
hero.setDirection(1);
hero.makeRight();
}
if(e.getKeyCode()==KeyEvent.VK_S) {
hero.setDirection(2);
hero.makeDown();
}
if(e.getKeyCode()==KeyEvent.VK_A){
hero.setDirection(3);
hero.makeLeft();
}
if(e.getKeyCode()==KeyEvent.VK_J){
hero.shotEnemy();
}
//重新绘制图像
this.repaint();
}
@Override
public void keyReleased(KeyEvent e) {
}
@Override
public void run(){
while (true){
try {
Thread.sleep(100);//子弹每隔0.5s重新绘制图像
} catch (InterruptedException e) {
e.printStackTrace();
}
//判断是否击中敌人坦克
//判断之前要求hero子弹不为null且存活
if(hero.getShot()!=null && hero.getShot().isLive()==true){
for(int i=0;i
hitEnemy(hero.getShot(),enemyTank.get(i));
}
}
this.repaint();
}
}
}
效果如下图:
让敌人坦克各自移动只需要在敌人坦克Enemy类上增加线程,在run()方法中写坦克移动的方式,并在创建敌人坦克时启动线程
Enemy:
public class Enemy extends Tank implements Runnable {
public Vector shots=new Vector<>();//vector容器中存放敌人的子弹
private boolean isLive=true;//敌人坦克是否存活
public Enemy(int x, int y) {
super(x, y);
}
public boolean isLive() {
return isLive;
}
public void setLive(boolean live) {
isLive = live;
}
@Override
public void run() {
while (isLive){
//根据当前坦克的方向(0向上1向左...)行走1次休息300毫秒,一共走30次
int step=50;
int time=30;
switch (getDirection()){
case 0:
for(int i=0;i
makeUp();
try {
Thread.sleep(time);
} catch (InterruptedException e) {
e.printStackTrace();
}
}
break;
case 1:
for(int i=0;i
makeRight();
try {
Thread.sleep(time);
} catch (InterruptedException e) {
e.printStackTrace();
}
}
break;
case 2:
for(int i=0;i
makeDown();
try {
Thread.sleep(time);
} catch (InterruptedException e) {
e.printStackTrace();
}
}
break;
case 3:
for(int i=0;i
makeLeft();
try {
Thread.sleep(time);
} catch (InterruptedException e) {
e.printStackTrace();
}
}
break;
}
//改变坦克方向[0,4)
setDirection((int)(Math.random()*4));
}
}
}
GamePanel:
public class GamePanel extends JPanel implements KeyListener,Runnable{
//在面板上定义自己的坦克Hero
Hero hero=null;
//在面板上用vector定义敌人坦克
Vector enemyTank=new Vector<>();
//设置敌人的坦克个数为3
int enemyTankSize=3;
//用vector定义爆炸
Vector bombs=new Vector<>();
//定义爆炸效果图片
Image[] images=new Image[3];
public GamePanel() {
//设置hero
hero= new Hero(100,100);//设置hero坦克的坐标
hero.setSpeed(3);//设置hero的速度
//for循环设置敌人的坦克
for(int i=0;i
Enemy enemy=new Enemy(100*(i+1),0);//第一个坦克的坐标为(100,0),第二个为(200,0)以此类推
enemy.setDirection(2);//设置坦克的方向向下(向下攻击己方坦克)
enemyTank.add(enemy);//在vector中添加当前创建的坦克
new Thread(enemy).start();
Shot shot=new Shot(enemy.getX()+20,enemy.getY()+60,2);//创建当前敌人的子弹
enemy.shots.add(shot);//将子弹添加在敌人类的vector容器中
new Thread(shot).start();//启动当前子弹进程
}
//设置图片
images[0]=Toolkit.getDefaultToolkit().getImage("D:\java-code\JavaCode\src\TankGames\bomb_1.gif");
images[1]=Toolkit.getDefaultToolkit().getImage("D:\java-code\JavaCode\src\TankGames\bomb_2.gif");
images[2]=Toolkit.getDefaultToolkit().getImage("D:\java-code\JavaCode\src\TankGames\bomb_3.gif");
}
//用画笔开始画
public void paint(Graphics g){
super.paint(g);//将g设置为画笔
// 填充矩形 fillRect(int x,int y,int width,int height)
g.fillRect(0,0,1000,750);
//绘制hero坦克
drawTank(hero.getX(),hero.getY(),g,0,hero.getDirection());
//如果子弹被创建或者子弹还存在就绘制子弹的图
if(hero.getShot()!=null&&hero.getShot().isLive()){
drawHeroShot(hero.getX(),hero.getY(),g);
}
//绘制敌人坦克
for(int i=0;i
//取出一个敌人
Enemy enemy=enemyTank.get(i);
//判断当前敌人坦克是否存活
if(enemy.isLive()==true){
//绘制取出的这个敌人
drawTank(enemy.getX(),enemy.getY(),g,1,enemy.getDirection());
//绘制当前敌人的子弹
for(int j=0;j
Shot shot=enemy.shots.get(j);//取出当前敌人的子弹
//如果shot存在,就绘制子弹;如果shot不存在,那么就从vector中移除子弹
if(shot.isLive()==true){
//绘制敌人子弹
g.setColor(Color.white);
g.draw3DRect(shot.getX(),shot.getY(),2,2,false);
}
else{
enemy.shots.remove(shot);//将shot从shots中移除
}
}
}
}
//绘制爆炸效果
for(int i=0;i
Bomb bomb=bombs.get(i);
if(bomb.getLifeCycle()>6){
}else if(bomb.getLifeCycle()>3){
g.drawImage(images[1],bomb.getX(),bomb.getY(),60,60,this);
}else
g.drawImage(images[2],bomb.getX(),bomb.getY(),60,60,this);
bomb.lifeCycleDown();//让爆炸生命周期减小
if(bomb.getLifeCycle()==0)//若爆炸的生命周期为0就将当前bomb从vector中移除
bombs.remove(bomb);
}
}
public void drawTank(int x,int y,Graphics g,int type,int direction){
switch (type){
case 0:
g.setColor(Color.blue);
break;
case 1:
g.setColor(Color.red);
break;
}
switch (direction){
case 0:
g.fill3DRect(x,y,10,60,false);//画出左轮子
g.fill3DRect(x+10,y+10,20,40,false);//画出右轮子
g.fill3DRect(x+30,y,10,60,false);//画出身体
g.fillOval(x + 10, y + 20, 20, 20);//画出圆形炮台
g.drawLine(x+20,y,x+20,y+20);//画出炮筒
break;
case 1:
g.fill3DRect(x,y,60,10,false);//画出左轮子
g.fill3DRect(x+10,y+10,40,20,false);//画出右轮子
g.fill3DRect(x,y+30,60,10,false);//画出身体
g.fillOval(x + 20, y + 10, 20, 20);//画出圆形炮台
g.drawLine(x+40,y+20,x+60,y+20);//画出炮筒
break;
case 2:
g.fill3DRect(x,y,10,60,false);//画出左轮子
g.fill3DRect(x+10,y+10,20,40,false);//画出右轮子
g.fill3DRect(x+30,y,10,60,false);//画出身体
g.fillOval(x + 10, y + 20, 20, 20);//画出圆形炮台
g.drawLine(x+20,y+40,x+20,y+60);//画出炮筒
break;
case 3:
g.fill3DRect(x,y,60,10,false);//画出左轮子
g.fill3DRect(x+10,y+10,40,20,false);//画出右轮子
g.fill3DRect(x,y+30,60,10,false);//画出身体
g.fillOval(x + 20, y + 10, 20, 20);//画出圆形炮台
g.drawLine(x,y+20,x+20,y+20);//画出炮筒
break;
}
}
public void drawHeroShot(int x, int y, Graphics g){
g.setColor(Color.white);
g.draw3DRect(hero.getShot().getX(),hero.getShot().getY(),2,2,false);
}
//hero坦克击中敌人坦克
public void hitEnemy(Shot shot,Enemy enemy){
switch (enemy.getDirection())
{
//如果敌人坦克方向向上/向下(0/2),hero坦克击中
case 0:
case 2:
//hero子弹在当前敌人坦克的区域
if(shot.getX()<=enemy.getX()+40 && shot.getX()>=enemy.getX() && shot.getY()>=enemy.getY() && shot.getY()<=enemy.getY()+60){
shot.setLive(false);//hero子弹销毁
enemy.setLive(false);//敌人销毁
//敌人销毁后爆炸效果创建
Bomb bomb=new Bomb(enemy.getX(),enemy.getY());//创建爆炸效果
bombs.add(bomb);//将爆炸效果添加在vector中
enemyTank.remove(enemy);
}
break;
case 1:
case 3:
if(shot.getX()<=enemy.getX()+60&&shot.getX()>=enemy.getX()&& shot.getY()>=enemy.getY() && shot.getY()<=enemy.getY()+40){
shot.setLive(false);//hero子弹销毁
enemy.setLive(false);//敌人销毁
//敌人销毁后爆炸效果创建
Bomb bomb=new Bomb(enemy.getX(),enemy.getY());//创建爆炸效果
bombs.add(bomb);//将爆炸效果添加在vector中
enemyTank.remove(enemy);
}
break;
}
}
@Override
public void keyTyped(KeyEvent e) {
}
@Override
public void keyPressed(KeyEvent e) {
if(e.getKeyCode()==KeyEvent.VK_W) { //若接受到键盘按下w
//坦克改变方向
hero.setDirection(0);
//坦克向上走1步
hero.makeUp();
}
if(e.getKeyCode()==KeyEvent.VK_D) {
hero.setDirection(1);
hero.makeRight();
}
if(e.getKeyCode()==KeyEvent.VK_S) {
hero.setDirection(2);
hero.makeDown();
}
if(e.getKeyCode()==KeyEvent.VK_A){
hero.setDirection(3);
hero.makeLeft();
}
if(e.getKeyCode()==KeyEvent.VK_J){
hero.shotEnemy();
}
//重新绘制图像
this.repaint();
}
@Override
public void keyReleased(KeyEvent e) {
}
@Override
public void run(){
while (true){
try {
Thread.sleep(100);//子弹每隔0.5s重新绘制图像
} catch (InterruptedException e) {
e.printStackTrace();
}
//判断是否击中敌人坦克
//判断之前要求hero子弹不为null且存活
if(hero.getShot()!=null && hero.getShot().isLive()==true){
for(int i=0;i
hitEnemy(hero.getShot(),enemyTank.get(i));
}
}
this.repaint();
}
}
}
限制敌人+自己坦克移动范围
只需要在控制敌人/自己坦克时,添加判断范围代码,判断范围要注意(x,y)表示左上角坐标
Enemy:
public class Enemy extends Tank implements Runnable {
public Vector shots=new Vector<>();//vector容器中存放敌人的子弹
private boolean isLive=true;//敌人坦克是否存活
public Enemy(int x, int y) {
super(x, y);
}
public boolean isLive() {
return isLive;
}
public void setLive(boolean live) {
isLive = live;
}
@Override
public void run() {
while (isLive){
//根据当前坦克的方向(0向上1向左...)行走1次休息time毫秒,一共走step次
int step=50;
int time=30;
switch (getDirection()){
case 0:
for(int i=0;i
if(getY()>0)
makeUp();
try {
Thread.sleep(time);
} catch (InterruptedException e) {
e.printStackTrace();
}
}
break;
case 1:
for(int i=0;i
if(getX()+60<1000)
makeRight();
try {
Thread.sleep(time);
} catch (InterruptedException e) {
e.printStackTrace();
}
}
break;
case 2:
for(int i=0;i
if(getY()+60<750)
makeDown();
try {
Thread.sleep(time);
} catch (InterruptedException e) {
e.printStackTrace();
}
}
break;
case 3:
for(int i=0;i
if(getX()>0)
makeLeft();
try {
Thread.sleep(time);
} catch (InterruptedException e) {
e.printStackTrace();
}
}
break;
}
//改变坦克方向[0,4)
setDirection((int)(Math.random()*4));
}
}
}
GamePanel:
public class GamePanel extends JPanel implements KeyListener,Runnable{
//在面板上定义自己的坦克Hero
Hero hero=null;
//在面板上用vector定义敌人坦克
Vector enemyTank=new Vector<>();
//设置敌人的坦克个数为3
int enemyTankSize=3;
//用vector定义爆炸
Vector bombs=new Vector<>();
//定义爆炸效果图片
Image[] images=new Image[3];
public GamePanel() {
//设置hero
hero= new Hero(100,100);//设置hero坦克的坐标
hero.setSpeed(3);//设置hero的速度
//for循环设置敌人的坦克
for(int i=0;i
Enemy enemy=new Enemy(100*(i+1),0);//第一个坦克的坐标为(100,0),第二个为(200,0)以此类推
enemy.setDirection(2);//设置坦克的方向向下(向下攻击己方坦克)
enemyTank.add(enemy);//在vector中添加当前创建的坦克
new Thread(enemy).start();
Shot shot=new Shot(enemy.getX()+20,enemy.getY()+60,2);//创建当前敌人的子弹
enemy.shots.add(shot);//将子弹添加在敌人类的vector容器中
new Thread(shot).start();//启动当前子弹进程
}
//设置图片
images[0]=Toolkit.getDefaultToolkit().getImage("D:\java-code\JavaCode\src\TankGames\bomb_1.gif");
images[1]=Toolkit.getDefaultToolkit().getImage("D:\java-code\JavaCode\src\TankGames\bomb_2.gif");
images[2]=Toolkit.getDefaultToolkit().getImage("D:\java-code\JavaCode\src\TankGames\bomb_3.gif");
}
//用画笔开始画
public void paint(Graphics g){
super.paint(g);//将g设置为画笔
// 填充矩形 fillRect(int x,int y,int width,int height)
g.fillRect(0,0,1000,750);
//绘制hero坦克
drawTank(hero.getX(),hero.getY(),g,0,hero.getDirection());
//如果子弹被创建或者子弹还存在就绘制子弹的图
if(hero.getShot()!=null&&hero.getShot().isLive()){
drawHeroShot(hero.getX(),hero.getY(),g);
}
//绘制敌人坦克
for(int i=0;i
//取出一个敌人
Enemy enemy=enemyTank.get(i);
//判断当前敌人坦克是否存活
if(enemy.isLive()==true){
//绘制取出的这个敌人
drawTank(enemy.getX(),enemy.getY(),g,1,enemy.getDirection());
//绘制当前敌人的子弹
for(int j=0;j
Shot shot=enemy.shots.get(j);//取出当前敌人的子弹
//如果shot存在,就绘制子弹;如果shot不存在,那么就从vector中移除子弹
if(shot.isLive()==true){
//绘制敌人子弹
g.setColor(Color.white);
g.draw3DRect(shot.getX(),shot.getY(),2,2,false);
}
else{
enemy.shots.remove(shot);//将shot从shots中移除
}
}
}
}
//绘制爆炸效果
for(int i=0;i
Bomb bomb=bombs.get(i);
if(bomb.getLifeCycle()>6){
}else if(bomb.getLifeCycle()>3){
g.drawImage(images[1],bomb.getX(),bomb.getY(),60,60,this);
}else
g.drawImage(images[2],bomb.getX(),bomb.getY(),60,60,this);
bomb.lifeCycleDown();//让爆炸生命周期减小
if(bomb.getLifeCycle()==0)//若爆炸的生命周期为0就将当前bomb从vector中移除
bombs.remove(bomb);
}
}
public void drawTank(int x,int y,Graphics g,int type,int direction){
switch (type){
case 0:
g.setColor(Color.blue);
break;
case 1:
g.setColor(Color.red);
break;
}
switch (direction){
case 0:
g.fill3DRect(x,y,10,60,false);//画出左轮子
g.fill3DRect(x+10,y+10,20,40,false);//画出右轮子
g.fill3DRect(x+30,y,10,60,false);//画出身体
g.fillOval(x + 10, y + 20, 20, 20);//画出圆形炮台
g.drawLine(x+20,y,x+20,y+20);//画出炮筒
break;
case 1:
g.fill3DRect(x,y,60,10,false);//画出左轮子
g.fill3DRect(x+10,y+10,40,20,false);//画出右轮子
g.fill3DRect(x,y+30,60,10,false);//画出身体
g.fillOval(x + 20, y + 10, 20, 20);//画出圆形炮台
g.drawLine(x+40,y+20,x+60,y+20);//画出炮筒
break;
case 2:
g.fill3DRect(x,y,10,60,false);//画出左轮子
g.fill3DRect(x+10,y+10,20,40,false);//画出右轮子
g.fill3DRect(x+30,y,10,60,false);//画出身体
g.fillOval(x + 10, y + 20, 20, 20);//画出圆形炮台
g.drawLine(x+20,y+40,x+20,y+60);//画出炮筒
break;
case 3:
g.fill3DRect(x,y,60,10,false);//画出左轮子
g.fill3DRect(x+10,y+10,40,20,false);//画出右轮子
g.fill3DRect(x,y+30,60,10,false);//画出身体
g.fillOval(x + 20, y + 10, 20, 20);//画出圆形炮台
g.drawLine(x,y+20,x+20,y+20);//画出炮筒
break;
}
}
public void drawHeroShot(int x, int y, Graphics g){
g.setColor(Color.white);
g.draw3DRect(hero.getShot().getX(),hero.getShot().getY(),2,2,false);
}
//hero坦克击中敌人坦克
public void hitEnemy(Shot shot,Enemy enemy){
switch (enemy.getDirection())
{
//如果敌人坦克方向向上/向下(0/2),hero坦克击中
case 0:
case 2:
//hero子弹在当前敌人坦克的区域
if(shot.getX()<=enemy.getX()+40 && shot.getX()>=enemy.getX() && shot.getY()>=enemy.getY() && shot.getY()<=enemy.getY()+60){
shot.setLive(false);//hero子弹销毁
enemy.setLive(false);//敌人销毁
//敌人销毁后爆炸效果创建
Bomb bomb=new Bomb(enemy.getX(),enemy.getY());//创建爆炸效果
bombs.add(bomb);//将爆炸效果添加在vector中
enemyTank.remove(enemy);
}
break;
case 1:
case 3:
if(shot.getX()<=enemy.getX()+60&&shot.getX()>=enemy.getX()&& shot.getY()>=enemy.getY() && shot.getY()<=enemy.getY()+40){
shot.setLive(false);//hero子弹销毁
enemy.setLive(false);//敌人销毁
//敌人销毁后爆炸效果创建
Bomb bomb=new Bomb(enemy.getX(),enemy.getY());//创建爆炸效果
bombs.add(bomb);//将爆炸效果添加在vector中
enemyTank.remove(enemy);
}
break;
}
}
@Override
public void keyTyped(KeyEvent e) {
}
@Override
public void keyPressed(KeyEvent e) {
if(e.getKeyCode()==KeyEvent.VK_W) { //若接受到键盘按下w
//坦克改变方向
hero.setDirection(0);
//坦克向上走1步
if(hero.getY()>0)
hero.makeUp();
}
if(e.getKeyCode()==KeyEvent.VK_D) {
hero.setDirection(1);
if(hero.getX()+60<1000)
hero.makeRight();
}
if(e.getKeyCode()==KeyEvent.VK_S) {
hero.setDirection(2);
if(hero.getY()+60<750)
hero.makeDown();
}
if(e.getKeyCode()==KeyEvent.VK_A){
hero.setDirection(3);
if(hero.getX()>0)
hero.makeLeft();
}
if(e.getKeyCode()==KeyEvent.VK_J){
hero.shotEnemy();
}
//重新绘制图像
this.repaint();
}
@Override
public void keyReleased(KeyEvent e) {
}
@Override
public void run(){
while (true){
try {
Thread.sleep(100);//子弹每隔0.5s重新绘制图像
} catch (InterruptedException e) {
e.printStackTrace();
}
//判断是否击中敌人坦克
//判断之前要求hero子弹不为null且存活
if(hero.getShot()!=null && hero.getShot().isLive()==true){
for(int i=0;i
hitEnemy(hero.getShot(),enemyTank.get(i));
}
}
this.repaint();
}
}
}



