Java之详解坦克大战游戏(四)

来源:互联网 发布:php计算九九加法表 编辑:程序博客网 时间:2024/06/06 04:07

目前我们的坦克能发子弹,但是只能发一颗,而且打到敌人坦克敌人还不会消失,本篇我们就来解决这个问题…子弹要想做到连发,就得初始化多个子弹,这个时候我们仍然还是跟定义敌人的坦克组一样用Vector集合..

class Hero extends Tank{    //子弹    Vector<Shot> ss = new Vector<Shot>();  //Vector集合    Shot s = null;    //...    //开火    public void shotEnemy()    {        switch (this.direct) //子弹的方向        {//s只是代号而已,指向谁就谁,不要理解它是同一颗子弹        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();    }

在到MyPanel类修改和添加代码

public void paint(Graphics g)    {        super.paint(g);        g.fillRect(0, 0, 1200, 900);  //填充使背景变为黑色           //从ss中取出每颗子弹,并画出        for(int i=0;i<hero.ss.size();i++)        {            Shot myShot = hero.ss.get(i);            //画出一颗子弹            if(myShot!=null && myShot.isLive == true)            {                g.setColor(Color.yellow);                g.draw3DRect(myShot.x, myShot.y, 1, 1, false);            }            if(myShot.isLive==false) //子弹死亡(下面将用到)            {                //从ss中删除该子弹                hero.ss.remove(myShot);            }        }

随着代码越写越多,可能我们会觉得很乱,这时看Eclipse编写代码页面右边有个Outline
这里写图片描述这里写图片描述
点一下就跳到我们要的类或方法了,比较容易看..

这时,子弹已经可以连发了..不过,打得还真是没有限制哦,无限连发,游戏都没难度了。所以,我们还是来设置一下连发限制吧..

public void keyPressed(KeyEvent e) {       //.......        //判断玩家是否按下j键        if(e.getKeyCode() == KeyEvent.VK_J)        {            if(this.hero.ss.size()<=4)//最多连发5颗子弹            {//为什么是<=4?因为进入shotEnemy后才由集合里面个数才由0变为1                //开火                this.hero.shotEnemy();            }        }}

这样最多能发五颗了,什么叫连发呢?上面paint方法有个子弹死亡的处理,也就是子弹打出后飞出界了或打到敌人坦克就算死亡,那么,接下来就要让敌人坦克碰到我们的子弹就消失吧..
这里我们写一个函数专门判断子弹是否会击中敌人坦克,先到Members.java文件中EnemyTank类添加一个变量isLive用于判断坦克的死活

boolean isLive=true; 
//写一个函数专门判断子弹是否会击中敌人坦克    public void hitTank(Shot s,EnemyTank 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;            }        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;            }        break;          }    }

接下来我们到TankGame3.java文件的run方法里面调用

public void run() {        //每隔100毫秒来重绘        while(true)        {            try {                Thread.sleep(100);            } catch (Exception e) {                // TODO: handle exception            }            //判断是否击中            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);                        }                    }                }            }            //重绘            this.repaint();        }    }

这个时候就可以让敌人坦克消失了,效果如图:
这里写图片描述
下篇讲如何让敌人坦克自由移动和打子弹,最后,附上此篇源代码
TankGame3.java

package com.TankGame3;import javax.swing.*;import java.awt.*;import java.awt.event.KeyEvent;import java.awt.event.KeyListener;import java.util.Vector;/* *  * */public class TankGame3 extends JFrame{    MyPanel mp =null;    public static void main(String[] args)     {        TankGame3 tankgame3 = new TankGame3();    }    public TankGame3()    {        mp=new MyPanel();        Thread t = new Thread(mp);        t.start();        this.addKeyListener(mp);//注册监听        this.setVisible(true);        this.setSize(400, 300);        this.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);        this.add(mp);    }}//我的面板class MyPanel extends Panel implements KeyListener,Runnable{//子弹要看到,要不停的重绘,paint函数每隔段时间久更新,重绘是在paint函数发生的,所以MyPanel要实现Runnable接口    //定义一个我的坦克    Hero hero =null;    //敌人的坦克组    Vector<EnemyTank> ets = new Vector<EnemyTank>();    int enSize=3; //敌人坦克初始数量    public MyPanel()    {        hero =new Hero(100,100); //坦克的初始位置(10,10)        //初始化敌人的坦克        for(int i=0;i<enSize;i++)        {            //创建一辆敌人的坦克对象            EnemyTank et =new EnemyTank((i+1)*50,0);            et.setColor(0);            et.setDirect(2);            //加入            ets.add(et);        }    }    //重新paint    public void paint(Graphics g)    {        super.paint(g);        g.fillRect(0, 0, 1200, 900);  //填充使背景变为黑色           //从ss中取出每颗子弹,并画出        for(int i=0;i<hero.ss.size();i++)        {            Shot myShot = hero.ss.get(i);            //画出一颗子弹            if(myShot!=null && myShot.isLive == true)            {                g.setColor(Color.yellow);                g.draw3DRect(myShot.x, myShot.y, 1, 1, false);            }            if(myShot.isLive==false)            {                //从ss中删除该子弹                hero.ss.remove(myShot);            }        }        //画出自己的坦克        this.drawTank(hero.getX(), hero.getY(), g, this.hero.direct, 1);        //画出敌人的坦克        for(int i=0;i<ets.size();i++)        {            EnemyTank et =ets.get(i);            if(et.isLive)            {                this.drawTank(et.getX(), et.getY(), g, et.getDirect(), 0);            }        }    }    //写一个函数专门判断子弹是否会击中敌人坦克    public void hitTank(Shot s,EnemyTank 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;            }        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;            }        }    }    //画出坦克的函数    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:            //画出我的坦克(到时再封装成一个函数)            //1.画出左边的矩形            g.fill3DRect(x, y, 5, 30,false);            //2.画出右边矩形            g.fill3DRect(x+15, y, 5, 30,false);            //3.画出中间矩形            g.fill3DRect(x+5, y+5, 10, 20,false);            //4.画出圆形            g.fillOval(x+5, y+10, 10, 10);            //5.画直线            g.drawLine(x+10, y+15, x+10, y);            break;        case 1://炮筒向右            //画出上面矩形            g.fill3DRect(x, y, 30, 5,false);            //2.画出右边矩形            g.fill3DRect(x, y+15, 30, 5,false);            //3.画出中间矩形            g.fill3DRect(x+5, y+5, 20, 10,false);            //4.画出圆形            g.fillOval(x+10, y+5, 10, 10);            //5.画直线            g.drawLine(x+15, y+10, x+30, y+10);            break;        case 2://炮筒向下            //画出上面矩形            g.fill3DRect(x, y, 5, 30,false);            //2.画出右边矩形            g.fill3DRect(x+15, y, 5, 30,false);            //3.画出中间矩形            g.fill3DRect(x+5, y+5, 10, 20,false);            //4.画出圆形            g.fillOval(x+5, y+10, 10, 10);            //5.画直线            g.drawLine(x+10, y+15, x+10, y+30);            break;        case 3://炮筒向左            //画出上面矩形            g.fill3DRect(x, y, 30, 5,false);            //2.画出右边矩形            g.fill3DRect(x, y+15, 30, 5,false);            //3.画出中间矩形            g.fill3DRect(x+5, y+5, 20, 10,false);            //4.画出圆形            g.fillOval(x+10, y+5, 10, 10);            //5.画直线            g.drawLine(x+15, y+10, x, y+10);            break;        }    }/*实现KeyListener接口的方法*/    //键入某个键时调用此方法。     public void keyTyped(KeyEvent e) {    }    //释放某个键时调用此方法    public void keyReleased(KeyEvent e) {    }    //按下某个键时调用此方法: a代表向左,w代表向上,d代表向右,s代表向下    public void keyPressed(KeyEvent e) {        if(e.getKeyCode() == KeyEvent.VK_W)//向上        {            this.hero.setDirect(0);            this.hero.moveUp();        }        else if(e.getKeyCode() == KeyEvent.VK_D)//向右        {            this.hero.setDirect(1);            this.hero.moveRight();        }        else if(e.getKeyCode() == KeyEvent.VK_S)//向下        {            this.hero.setDirect(2);            this.hero.moveDown();        }        else if(e.getKeyCode() == KeyEvent.VK_A)//向左        {            this.hero.setDirect(3);            this.hero.moveLeft();        }        //判断玩家是否按下j键        if(e.getKeyCode() == KeyEvent.VK_J)        {            //开火            if(this.hero.ss.size()<=4)  //子弹最多连发5颗            {            this.hero.shotEnemy();            }        }        this.repaint();//调用repaint()函数,来重绘页面    }    public void run() {        //每隔100毫秒来重绘        while(true)        {            try {                Thread.sleep(100);            } catch (Exception e) {                // TODO: handle exception            }            //判断是否击中            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);                        }                    }                }            }            //重绘            this.repaint();        }    }}

Members.java

package com.TankGame3;import java.util.Vector;//坦克类class Tank{    //表示坦克的横坐标    int x=0;    //表示坦克的纵坐标    int y=0;    //坦克方向     //0表示上,1表示右,2表示下,3表示左    int direct=0;    int color;//坦克的颜色    public int getColor() {        return color;    }    public void setColor(int color) {        this.color = color;    }    public int getDirect() {        return direct;    }    public void setDirect(int derect) {        this.direct = derect;    }    //坦克速度    int speed=1;    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{    boolean isLive=true;    public EnemyTank(int x, int y) {        super(x, y);    }}//我的坦克class Hero extends Tank{    //子弹    //Shot s = null;    Vector<Shot> ss = new Vector<Shot>();    Shot s=null;    public Hero(int x,int y)    {        super(x,y);    }    //开火    public void shotEnemy()    {        switch (this.direct) //子弹的方向        {//s只是代号而已,指向谁就谁,不要理解它是同一个子弹        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();    }    //坦克向上移动    public void moveUp()    {        y-=speed;    }    //坦克向右移动    public void moveRight()    {        x+=speed;    }    //坦克向下移动    public void moveDown()    {        y+=speed;    }    //坦克向左移动    public void moveLeft()    {        x-=speed;    }}//子弹类class Shot implements Runnable{    int x;    int y;    int direct;//子弹的方向    int speed=1; //子弹速度    boolean isLive=true;//子弹是否活着    public Shot(int x,int y,int direct)    {        this.x=x;        this.y=y;        this.direct=direct;    }    public void run() {        while(true)        {            try {                Thread.sleep(50);            } catch (Exception e) {                // TODO: handle exception            }            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>400 || y<0 || y>300)            {                this.isLive=false;                break;            }        }    }}
0 0
原创粉丝点击