频道栏目
首页 > 资讯 > Java实例 > 正文

JAVA写的坦克大战(单机图片版)

16-06-27        来源:[db:作者]  
收藏   我要投稿

第一次写那么大的程序(感觉还是不错)

这里写图片描述
这里写图片描述
这里写图片描述
这里写图片描述


package _25增加配置文件;

import java.awt.*;
import java.awt.event.*;
import java.util.List;

import java.util.ArrayList;
/**
 * 这是这款游戏的主窗口,各个类都有他的引用
 * @author ☆东★
 *
 */
public class TankClient extends Frame{
    private Image offScreamImage = null;
    public static int WIDTH,HEIGHT;
    public int times = 0;//用来表示发了几发炮弹
    public List myBullets = new ArrayList();//代表还有几发炮弹
    public List explodes = new ArrayList();
    public List enemyTank = new ArrayList();
    public Tank myTank = new Tank(50,500,true,Direction.STOP,this);//把TankClient对象传进去,使Tank可以操作TankClient里面的部分数据

    public int width = Toolkit.getDefaultToolkit().getScreenSize().width;
    public int height = Toolkit.getDefaultToolkit().getScreenSize().height;

    public Wall wall1 = new Wall(100,100,20,200,this);
    public Wall wall2 = new Wall(300,450,70,70,this);
    public Blood b = new Blood(this);
    private boolean GAME_OVER = false;

    /**
     * 这个方法时画出图形的主要方法,其他类实现的图形,最终都要放到这个方法中
     */
    public void paint(Graphics g) {
        wall1.draw(g);
        wall2.draw(g);
        b.draw(g);
        myTank.drawTank(g);
        myTank.eat(b);

        /**
         * 当敌人没有了,就再生成一些敌人
         */
        if(enemyTank.size()==0){
            int reinitTank = Integer.parseInt(GetProp.getProp("reTankCount"));
            for(int i = 0;i=30){
            g.drawString("还有多少发炮弹:"+0, 10, 50);
            g.setColor(Color.red);
            g.drawString("没炮弹了(充钱)", 20, 75);
        }
        else{
            g.drawString("还有多少发炮弹:"+(30-times), 10, 50);
            g.drawString("敌方坦克:"+enemyTank.size(), 10, 70);
        }
        /**
         * 画子弹,当子弹没有了,就不能画子弹了
         */
        if(myBullets.size()!=0)
        for(int i=0;i
package _25增加配置文件;

import java.awt.*;
import java.awt.event.*;
import java.util.*;
/**
 * 画坦克的主要类
 * @author ☆东★
 *
 */
public class Tank {
    private int x,y;// x  y  代表了tank现在的位置
    private int oldX,oldY;//记录坦克上一步的位置
//  private static final int WIDTH = 30,HEIGHT = 30;//坦克大小
    private static final int WIDTH = 50,HEIGHT = 50;//坦克大小
    private static final int XSPEED = 5,YSPEED = 5;//坦克xy方向运动速度 
    public int GAME_LEVEL = 14;//默认游戏难度为12  越高越简单,最高17  最低3
    //想让Tank向8个方向走
    private boolean bL = false ,bU = false ,bR = false ,bD = false;//用于记录  键盘按下的  上下左右  (按下之后就设置为True)
    private Direction dir = Direction.STOP;//坦克的最开始的方向
    private Direction ptDir = Direction.D;//炮筒最开始的方向
    private TankClient tc = null;
    private boolean good ;
    private boolean live = true;
    private static Random rand = new Random();
    private int step = rand.nextInt(15)+3;//设置随机朝一个方向移动的步数,不然老是在同一个地方乱动
    private int life = 100;//给我方坦克设置血量
    private BloodBar bb  = new BloodBar();

    /**
     * 增加图片
     */
    private static Toolkit tk = Toolkit.getDefaultToolkit();
    private static Map imags = new HashMap();
    private static Image[] tankImage = null;
    static {
        tankImage = new Image[]{
                tk.getImage(Explode.class.getClassLoader().getResource("images/tankL.gif")),
                tk.getImage(Explode.class.getClassLoader().getResource("images/tankLU.gif")),
                tk.getImage(Explode.class.getClassLoader().getResource("images/tankU.gif")),
                tk.getImage(Explode.class.getClassLoader().getResource("images/tankRD.gif")),
                tk.getImage(Explode.class.getClassLoader().getResource("images/tankR.gif")),
                tk.getImage(Explode.class.getClassLoader().getResource("images/tankRU.gif")),
                tk.getImage(Explode.class.getClassLoader().getResource("images/tankD.gif")),
                tk.getImage(Explode.class.getClassLoader().getResource("images/tankLD.gif"))
        };
        imags.put("L", tankImage[0]);
        imags.put("LU", tankImage[1]);
        imags.put("U", tankImage[2]);
        imags.put("RD", tankImage[3]);
        imags.put("R", tankImage[4]);
        imags.put("RU", tankImage[5]);
        imags.put("D", tankImage[6]);
        imags.put("LD", tankImage[7]);
    }

    public int getLife() {
        return life;
    }
    public void setLife(int life) {
        this.life = life;
    }
    public void setGood(boolean good) {
        this.good = good;
    }
    public boolean isGood() {
        return good;
    }
    public boolean isLive() {
        return live;
    }
    public void setLive(boolean live) {
        this.live = live;
    }

    public Tank(int x,int y,boolean good,Direction dir,TankClient tc){//获取TankClient的引用,让Tank可以调用TankClient里面的数据,因为子弹的方向是由Tank决定的,而TankClient要获取Bullets方向
        this.x = x;
        this.y = y;
        this.good = good;
        this.dir = dir;
        this.tc = tc;
    }

    public void drawTank(Graphics g){//坦克自己画自己
        if(!live){
            tc.enemyTank.remove(this);
            return;
        }

        if(good){
            bb.draw(g);
        }

        ptDraw(g);//画炮筒

        move();
    }
    /**
     * 用于判断  tank 往哪个方向走        用枚举里面的数   来判断是往哪个方向走的    从此 x y 的改变就从move这个方法里面改变(原来是从KeyAdapter 里面改变的)
     */
    private void move(){
        oldX = x;//记录上一步的位置
        oldY = y;

        switch(dir){//dir决定最终坦克的方向
        case L : 
            x-=XSPEED; break;
        case LU :
            x-=XSPEED; y-=YSPEED; break;
        case U :
            y-=XSPEED; break;
        case RD :
            x+=XSPEED; y+=YSPEED; break;
        case R :
            x+=XSPEED; break;
        case RU :
            x+=XSPEED; y-=YSPEED; break;
        case D :
            y+=YSPEED; break;
        case LD :
            x-=XSPEED; y+=YSPEED; break;
        case STOP : break;
        }
        /**
         * 判断是否出界
         */
        if(x<=5)
            x = 5;
        if(y<=30)
            y = 30;
        if(x>=TankClient.WIDTH-Tank.WIDTH-5)
            x = TankClient.WIDTH-Tank.WIDTH-5;
        if(y>=TankClient.HEIGHT-Tank.HEIGHT-5)
            y=TankClient.HEIGHT-Tank.HEIGHT-5;

        /**
         * 给炮筒一个方向
         */
        if(this.dir != Direction.STOP)//如果地方坦克   坦克方向不为Stop,,那么改变炮筒方向(与坦克方向一样)
            ptDir = dir;
        /**
         * 让炮筒发射子弹
         */
        if(!good){//如果是敌方坦克
            if(step == 0){
                Direction[] arr = Direction.values();// 把enum转化为数组
                int r = rand.nextInt(arr.length);//从0到arr的最大长度
                dir = arr[r];
                step = rand.nextInt(15)+3;//生成0---14之间的数

                //给敌方tank增加炮弹。。不能太密集
                if(step>=GAME_LEVEL) fire();
            }
            step--;
        }
    }
    /**
     * 画出炮筒
     * @param g
     */
    private void ptDraw(Graphics g){
        switch(ptDir){
        case L : 
            g.drawImage(imags.get("L"),x, y, null); break;
        case LU :
            g.drawImage(imags.get("LU"),x, y, null); break;
        case U :
            g.drawImage(imags.get("U"),x, y, null); break;
        case RD :
            g.drawImage(imags.get("RD"),x, y, null); break;
        case R :
            g.drawImage(imags.get("R"),x, y, null); break;
        case RU :
            g.drawImage(imags.get("RU"),x, y, null); break;
        case D :
            g.drawImage(imags.get("D"),x, y, null); break;
        case LD :
            g.drawImage(imags.get("LD"),x, y, null); break;
        case STOP :
            g.drawImage(imags.get("STOP"),x, y, null); break;
        }
    }
    /**
     * Tank真正走的方向  L, LU, U, RD, R, RU, D, LD, STOP   取决于dir的值
     */
    private void realDirection(){
        if(bL && !bU && !bR && !bD)
            dir = Direction.L;
        else if(bL && bU && !bR && !bD)
            dir = Direction.LU;
        else if(!bL && bU && !bR && !bD)
            dir = Direction.U;
        else if(!bL && !bU && bR && bD)
            dir = Direction.RD;
        else if(!bL && !bU && bR && !bD)
            dir = Direction.R;
        else if(!bL && bU && bR && !bD)
            dir = Direction.RU;
        else if(!bL && !bU && !bR && bD)
            dir = Direction.D;
        else if(bL && !bU && !bR && bD)
            dir = Direction.LD;
        else if(!bL && !bU && !bR && !bD)
            dir = Direction.STOP;
    }
    /**
     * Tank发射子弹   给子弹一个信号,,让子弹往自己指定的方向发子弹
     */
    private void fire(){
        if(good)
            tc.times++;//每次 发子弹的时候,设置一个计数器

        int x = this.x + Tank.WIDTH/2 - Bullets.WIDTH/2;
        int y = this.y + Tank.HEIGHT/2 - Bullets.HEIGHT/2;
        Bullets b = new Bullets(x,y,ptDir,good,tc);

        if(!good)//地方塔克可以一直创建子弹
            tc.myBullets.add(b);
        else if(tc.times<30 && live){//如果是我方坦克,发子弹次数少于20次,而且坦克活着,那么就装一发炮弹
            tc.myBullets.add(b);
        }//这样做保证了,当自己的子弹用完了,敌方还可以发炮弹
    }
    /**
     * 超级炮筒
     */
    private void superFire(){
        Direction[] arr = dir.values();//转化为数组
        for(int i = 0;i<8;i++){
            fire(arr[i]);
        }
        tc.times += 4;//相当于给散弹多一点子弹  发一发相当于以前发4发
    }
    /**
     * 发射超级炮弹
     * @param dir 不受炮筒方向控制的炮弹
     */
    private void fire(Direction dir){
        int x = this.x + Tank.WIDTH/2 - Bullets.WIDTH/2;
        int y = this.y + Tank.HEIGHT/2 - Bullets.HEIGHT/2;
        Bullets b = new Bullets(x,y,dir,good,tc);

        if(tc.times<30 && live){//如果是我方坦克,发子弹次数少于80次
            tc.myBullets.add(b);
        }
    }
    /**
     * 判断两个矩形是否相碰的方法
     * @return 返回值在判断是否相碰会用到
     */
    public Rectangle getRect(){
        return new Rectangle(x,y,WIDTH,HEIGHT);
    }
    /**
     * 判断是否撞墙
     * @param w 墙
     */
    public void hitWall(Wall w){
        if(live && this.getRect().intersects(w.getRect())){
            x = oldX;
            y = oldY;
        }
    }
    public void hitTank(java.util.List tanks){
        for(int i = 0;i
package _25增加配置文件;

import java.awt.Color;
import java.awt.Graphics;
import java.awt.Image;
import java.awt.Toolkit;
/**
 * 爆炸类
 * @author ☆东★
 *
 */
public class Explode {//爆炸
    private int x , y;
    private boolean live = true;
    private int step = 0;//画到第几步了
    private TankClient tc;
    private static boolean init;
    private static Toolkit tk = Toolkit.getDefaultToolkit();
    private static Image[] image = {
            tk.getImage(Explode.class.getClassLoader().getResource("images/0.gif")),
            tk.getImage(Explode.class.getClassLoader().getResource("images/1.gif")),
            tk.getImage(Explode.class.getClassLoader().getResource("images/2.gif")),
            tk.getImage(Explode.class.getClassLoader().getResource("images/3.gif")),
            tk.getImage(Explode.class.getClassLoader().getResource("images/4.gif")),
            tk.getImage(Explode.class.getClassLoader().getResource("images/5.gif")),
            tk.getImage(Explode.class.getClassLoader().getResource("images/6.gif")),
            tk.getImage(Explode.class.getClassLoader().getResource("images/7.gif")),
            tk.getImage(Explode.class.getClassLoader().getResource("images/8.gif")),
            tk.getImage(Explode.class.getClassLoader().getResource("images/9.gif")),
            tk.getImage(Explode.class.getClassLoader().getResource("images/10.gif"))
    };

    Explode(int x,int y,TankClient tc){
        this.x = x;
        this.y = y;
        this.tc = tc;
    }

    public void draw(Graphics g){
        if(!init){
            for (int i = 0; i< image.length; i++) {//会发现第一次打敌人,不会出现爆炸。可能是系统第一次 加载图片的时候不会放到内存中
                g.drawImage(image[i], 100, 100, null);
            }
            init = true;
        }

        if(!live){
            tc.explodes.remove(this);//当爆炸不存在了,就从TankClient的爆炸集合中移除当前爆炸
            return ;
        }
        if(step==11){
            this.live = false;
            this.step = 0;
            return ;
        }
        g.drawImage(image[step++], x, y, null);
    }
}
package _25增加配置文件;
/**
 * 方向的枚举
 * @author ☆东★
 *
 */
public enum Direction {
    L, LU, U, RD, R, RU, D, LD, STOP//用来表示Tank是朝 哪个方法走的   以后这个枚举就来代表坦克的走向
}
package _25增加配置文件;

import java.awt.*;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
/**
 * 子弹类
 * @author ☆东★
 *
 */
public class Bullets {//子弹类
    private int x,y;//坦克的位置,也是子弹的位置
    private boolean live = true;
    public static final int WIDTH = 10, HEIGHT = 10;//子弹大小
    private static final int XSPEED = 10,YSPEED = 10;//子弹速度
    private TankClient tc;
    private boolean good;//用于标识子弹是哪一方的子弹
    Direction dir;

    private static Toolkit tk = Toolkit.getDefaultToolkit();
    private static Map imags = new HashMap();
    private static Image[] tankImage = null;
    static {
        tankImage = new Image[]{//L, LU, U, RD, R, RU, D, LD, STOP
                tk.getImage(Explode.class.getClassLoader().getResource("images/missileL.gif")),
                tk.getImage(Explode.class.getClassLoader().getResource("images/missileLU.gif")),
                tk.getImage(Explode.class.getClassLoader().getResource("images/missileU.gif")),
                tk.getImage(Explode.class.getClassLoader().getResource("images/missileRD.gif")),
                tk.getImage(Explode.class.getClassLoader().getResource("images/missileR.gif")),
                tk.getImage(Explode.class.getClassLoader().getResource("images/missileRU.gif")),
                tk.getImage(Explode.class.getClassLoader().getResource("images/missileD.gif")),
                tk.getImage(Explode.class.getClassLoader().getResource("images/missileLD.gif"))
        };
        imags.put("L", tankImage[0]);
        imags.put("LU", tankImage[1]);
        imags.put("U", tankImage[2]);
        imags.put("RD", tankImage[3]);
        imags.put("R", tankImage[4]);
        imags.put("RU", tankImage[5]);
        imags.put("D", tankImage[6]);
        imags.put("LD", tankImage[7]);
    }

    public Bullets(int x,int y,Direction dir,boolean good,TankClient tc){
        this.x = x;
        this.y = y;
        this.dir = dir;
        this.good = good;
        this.tc = tc;
    }

    public void draw(Graphics g){
        if(!live){
            tc.myBullets.remove(this);//用于删除子弹。不然这一发子弹打中敌人,另一个敌人来到这个地方也会死
            return;
        }
        if(good){
            Color c = g.getColor();
            g.setColor(Color.black);
            g.fillOval( x, y, WIDTH, HEIGHT);
            g.setColor(c);
        }

            switch(dir){
            case L : 
                g.drawImage(imags.get("L"),x, y, null); break;
            case LU :
                g.drawImage(imags.get("LU"),x, y, null); break;
            case U :
                g.drawImage(imags.get("U"),x, y, null); break;
            case RD :
                g.drawImage(imags.get("RD"),x, y, null); break;
            case R :
                g.drawImage(imags.get("R"),x, y, null); break;
            case RU :
                g.drawImage(imags.get("RU"),x, y, null); break;
            case D :
                g.drawImage(imags.get("D"),x, y, null); break;
            case LD :
                g.drawImage(imags.get("LD"),x, y, null); break;
            case STOP :
                g.drawImage(imags.get("STOP"),x, y, null); break;
            }

        move();
    }

    //子弹自己的移动方向速度
    private void move() {
        switch(dir){
        case L : 
            x-=XSPEED; break;
        case LU :
            x-=XSPEED; y-=YSPEED; break;
        case U :
            y-=XSPEED; break;
        case RD :
            x+=XSPEED; y+=YSPEED; break;
        case R :
            x+=XSPEED; break;
        case RU :
            x+=XSPEED; y-=YSPEED; break;
        case D :
            y+=YSPEED; break;
        case LD :
            x-=XSPEED; y+=YSPEED; break;
        }

        if(x<0 || y<0 || x>TankClient.WIDTH || y>TankClient.HEIGHT){//子弹超出边界  就让他在子弹集合中删除
            live = false;
        }
    }

    public Rectangle getRect(){
        return new Rectangle(x,y,WIDTH,HEIGHT);
    }


    //下面就是判断  坦克是否被击中,一级击中后会发生的事,一个函数可以解决,第一个函数里面就是循环,可以把它放在第二个函数里(只是不容易看而已)
    public void hitTanks(List tanks){
        for(int i=0;i
package _25增加配置文件;

import java.awt.Color;
import java.awt.Graphics;
import java.awt.Rectangle;
import java.util.Random;
/**
 * 血量类
 * @author ☆东★
 *
 */
public class Blood {
    private int x ,y , w ,h;
    private TankClient tc;
    private boolean live = true;
    private Random rand = new Random();


    Blood(TankClient tc){
        this.tc = tc;
    }

    public boolean isLive() {
        return live;
    }
    public void setLive(boolean live) {
        this.live = live;
    }

    public void draw(Graphics g){
        if(!live) return ;
        x = rand.nextInt(tc.WIDTH/50)+600;
        y = rand.nextInt(tc.HEIGHT/50)+150;
        Color c = g.getColor();
        g.setColor(Color.green);
        g.fillRect(x, y, 20, 20);
        g.setColor(c);
    }

    public Rectangle getRect(){
        return new Rectangle(x, y, 20, 20);
    }

}
package _25增加配置文件;

import java.awt.Graphics;
import java.awt.Rectangle;
/**
 * 墙类
 * @author ☆东★
 *
 */
public class Wall {
    private int x,y,w,h;
    private TankClient tc;

    public Wall(int x, int y, int w, int h, TankClient tc) {
        super();
        this.x = x;
        this.y = y;
        this.w = w;
        this.h = h;
        this.tc = tc;
    }

    public void draw(Graphics g){
        g.fillRect(x, y, w, h);
    }

    public Rectangle getRect(){
        return new Rectangle(x,y,w,h);
    }

}
package _25增加配置文件;

import java.io.IOException;
import java.util.Properties;

/**
 * 使用配置文件,,采用了单例设计模式
 * @author ☆东★
 *
 */
public class GetProp {
    private static Properties prop = new Properties();

    static{
        try {
            prop.load(GetProp.class.getClassLoader().getResourceAsStream("config/tank.properties"));
        } catch (IOException e1) {
            e1.printStackTrace();
        }
    }

    private GetProp(){}

    public static String getProp(String key){
        return prop.getProperty(key);
    }

}
initTankCount=15
reTankCount=10
相关TAG标签
上一篇:操作系统实现之内存分页机制.虚拟空间
下一篇:ArrayList和LinkList剖析
相关文章
图文推荐

关于我们 | 联系我们 | 广告服务 | 投资合作 | 版权申明 | 在线帮助 | 网站地图 | 作品发布 | Vip技术培训 | 举报中心

版权所有: 红黑联盟--致力于做实用的IT技术学习网站