【潜艇游戏开发】最全的源代码

## 潜艇游戏第一天:

1. 创建了6个类,创建World类并测试

## 潜艇游戏第二天:

1. 给6个类设计构造方法,并测试

## 潜艇游戏第三天:

1. 设计侦察潜艇数组、鱼雷潜艇数组、水雷潜艇数组、水雷数组、炸弹数组,并测试

2. 设计SeaObject超类,设计6个类继承SeaObject

3. 在超类SeaObject中设计两个构造方法,6个派生类分别调用

4. 将侦察潜艇数组、鱼雷潜艇数组、水雷潜艇数组统一组合成SeaObject数组,并测试

## 潜艇游戏第四天:

1. 在6个类中重写move()移动
2. 给类中成员添加访问权限
3. 设计Images图片类

## 潜艇游戏第五天:

1. 设计窗口的宽和高为常量,适用地方做修改

2. 画窗口:--

   - import JFrame+JPanel
   - 设计World类继承JPanel----------------这一步大家特别容易忘记
   - main中代码CV大法

3. 画对象:

   ```java
   1)想画对象需要获取对象的图片,每个对象都能得图片,
     意味着获取图片的行为为共有行为,所以设计在SeaObject类中,
     每个对象获取图片的代码都是不一样的,所以设计为抽象方法
     ----在SeaObject中设计抽象方法getImage()获取图片
   2)在派生类中重写getImage()获取对象所对应的图片
     ----在6个类中重写getImage()
   3)因为只有活着的对象才需要画到窗口中,所以需要设计对象的状态(活着还是死了),
     每个对象都有状态,意味着状态为共有属性,所以设计在SeaObject超类中,
     状态一般都设计为常量,同时再设计state变量表示当前状态
     ----在SeaObject中设计LIVE、DEAD常量,state变量表示当前状态
     在后期的业务中经常需要判断对象的状态,每个对象都得判断,
     意味着判断状态的行为为共有行为,所以设计在SeaObject超类中,
     每个对象判断状态的代码都是一样的,所以设计为普通方法
     ----在SeaObject中设计isLive()、isDead()判断对象的状态
   4)数据(状态、图片、x坐标、y坐标)都有了就可以开画了,每个对象都得画,
     意味着画对象的行为为共有行为,所以设计在SeaObject超类中,
     每个对象画的代码都是一样的,所以设计为普通方法
     ----在SeaObject中设计paintImage()画对象
   5)画对象的方法写好了,在窗口World类中调用即可:
     5.1)准备对象
     5.2)重写paint()方法---在paint()中调用paintImage()即可---------不要求掌握
   ```

## 潜艇游戏第六天:---------要求:能够按照步骤写出来就OK

1. 潜艇入场:

   - 潜艇对象是由窗口产生的,所以在World类中设计nextSubmarine()生成潜艇对象

   - 潜艇入场为定时发生的,所以在run()中调用submarineEnterAction()实现潜艇入场

     - 在submarineEnterAction()中:
       - 每400毫秒,获取潜艇对象obj,submarines扩容,将obj添加到submarines最后一个元素上

     > 注意:run()中调用submarineEnterAction()后,一定要调用repaint()来重画

2. 水雷入场(上半段):

   - 水雷对象是由水雷潜艇发射出来的,所以在MineSubmarine中设计shootMine()生成水雷对象
   - 水雷入场为定时发生的,所以在run()中调用mineEnterAction()实现水雷入场
     - 在mineEnterAction()中:
       - 每1000毫秒,......暂时搁置

3. 海洋对象移动:

   - 海洋对象移动为共有的行为,所以在SeaObject中设计抽象方法move(),6个派生类中重写move()移动
   - 海洋对象移动为定时发生的,所以在run()中调用moveAction()实现海洋对象移动
     - 在moveAction()中:
       - 遍历所有潜艇,潜艇移动。遍历所有水雷,水雷移动,遍历所有炸弹,炸弹移动。

## 潜艇游戏第七天:---------要求:能够按照步骤写出来就OK

1. 炸弹入场:

   - 炸弹是由战舰发射出来的,所以在Battleship中设计shootBomb()生成炸弹对象
   - 炸弹入场为事件触发的,所以在侦听器中重写keyReleased()按键抬起方法,方法中判断:
     - 若抬起的是空格键,则:
       - 获取炸弹对象obj,bombs扩容,将obj装到最后一个元素上

2. 战舰移动:

   - 战舰移动为战舰的行为,所以在Battleship中设计moveLeft()左移、moveRight()右移
   - 战舰移动为事件触发的,所以在侦听器的重写keyReleased()按键抬起方法中判断:
     - 若抬起的是左箭头,则战舰左移
     - 若抬起的是右箭头,则战舰右移

3. 删除越界的海洋对象:

   - 在SeaObject中设计isOutOfBounds()检测潜艇越界,在Bomb和Mine中重写isOutOfBounds()检测炸弹和水雷越界
   - 删除越界的海洋对象是定时发生的,所以在run()中调用outOfBoundsAction()删除越界的海洋对象
     - 在outOfBoundsAction()中:
       - 遍历所有潜艇/水雷/炸弹数组,判断若越界了,则:
         - 将越界元素替换为最后一个元素,缩容

4. 设计EnemyScore分的接口,侦察潜艇与鱼雷潜艇实现分的接口

   设计EnemyLife命的接口,水雷潜艇实现命的接口

## 潜艇游戏第八天:---------要求:能够按照步骤写出来就OK

1. 水雷入场(下半段):

   - 水雷对象是由水雷潜艇发射出来的,所以在MineSubmarine中设计shootMine()生成水雷对象
   - 水雷入场为定时发生的,所以在run()中调用mineEnterAction()实现水雷入场
     - 在mineEnterAction()中:
       - 每1000毫秒,遍历所有潜艇,判断若为水雷潜艇,则强转为水雷潜艇类型:
         - 获取水雷对象obj,扩容,将obj添加到最后一个元素上

2. 炸弹与潜艇的碰撞:

   - 在SeaObject中设计isHit()检测碰撞、goDead()海洋对象去死

     在Battleship中设计addLife()增命

   - 炸弹与潜艇的碰撞为定时发生的,所以在run()中调用bombBangAction()实现炸弹与潜艇碰撞

     - 在bombBangAction()中:
       - 遍历所有炸弹得炸弹,遍历所有潜艇得潜艇,判断若都活着并且还撞上了:
         - 潜艇去死、炸弹去死
         - 判断若是分,则强转为分的接口,玩家得分
         - 判断若是命,则强转为命的接口,获取命数,战舰得命

3. 画分和画命:

   - 在Battleship中设计getLife()获取命数
   - 在paint()中:画分和画命---------------------不要求掌握

## 潜艇游戏第九天:---------要求:能够按照步骤写出来就OK

1. 水雷与战舰的碰撞:
   - 在Battleship中设计subtractLife()减命
   - 水雷与战舰的碰撞为定时发生的,所以在run()中调用mineBangAction()实现水雷与战舰碰撞
     - 在mineBangAction()中:
       - 遍历水雷获取水雷,判断若都活着并且还撞上了:
         - 水雷去死、战舰减命
2. 检测游戏结束:
   - 借用Battleship类的getLife()获取命数
   - 检测游戏结束为定时发生的,所以在run()中调用checkGameOverAction()检测游戏结束
     - 在checkGameOverAction()中:
       - 若战舰的命数<=0,表示游戏结束,则......
3. 画状态:
   - 在World类中设计RUNNING、PAUSE、GAME_OVER状态常量,state变量表示当前状态
   - 在checkGameOverAction()中,若游戏结束,则将state修改为GAME_OVER游戏结束状态
   - 在paint()设计:当游戏结束时画游戏结束图
   - 设计run中的那一堆代码为仅在运行状态时执行
   - 设计重写keyReleased()中的那一堆代码为仅在运行状态时执行
   - 设计若抬起的是P键,则运行状态变为暂停状态,暂停状态变为运行状态

以下代码为最终的

Battleship

package cn.tedu.submarine;

import javax.swing.ImageIcon;

/**
 * 战舰类
 */
public class Battleship extends SeaObject {
    private int life;   //命

    /**
     * 构造方法
     */
    public Battleship(){
        super(66,26,270,124,20);
        life = 5;
    }

    /**
     * 重写move()移动
     */
    public void move(){
        //暂时搁置
    }

    /**
     * 重写getImage()获取对象图片
     * @return 返回战舰图片
     */
    public ImageIcon getImage(){
        return Images.battleship; //返回战舰图片
    }

    /**
     * 发射炸弹----生成炸弹对象
     * @return 炸弹对象
     */
    public Bomb shootBomb(){
        return new Bomb(this.getX(),this.getY()); //炸弹的初始坐标就是战舰的坐标
    }

    /**
     * 战舰左移
     */
    public void moveLeft(){
        setX(getX()-getSpeed()); //x-(向左)
    }

    /**
     * 战舰右移
     */
    public void moveRight(){
        setX(getX()+getSpeed()); //x+(向右)
    }

    /**
     * 战舰增命
     * @param num 所增命的数量
     */
    public void addLife(int num){
        life += num; //命数增num
    }

    /**
     * 获取战舰的命数
     * @return 返回战舰命数
     */
    public int getLife(){
        return life; //返回命数
    }

    /** 战舰减命 */
    public void subtractLife(){
        life--; //命数减1
    }

}



Bomb

package cn.tedu.submarine;

import javax.swing.*;

/**
 * 炸弹类
 */
public class Bomb extends SeaObject {
    /**
     * 构造方法
     * @param x 炸弹的初始x坐标
     * @param y 炸弹的初始y坐标
     */
    public Bomb(int x,int y){ //因为炸弹的初始坐标,是根据战舰的坐标计算出来的,所以不能写死
        super(9,12,x,y,3);
    }

    /**
     * 重写move()移动
     */
    public void move(){
        setY(getY()+getSpeed()); //y+(向下)
    }

    /**
     * 重写getImage()获取对象图片
     * @return 返回炸弹图片
     */
    public ImageIcon getImage(){
        return Images.bomb; //返回炸弹图片
    }

    /**
     * 重写isOutOfBounds()检测炸弹是否越界
     * @return 若越界则返回true,否则返回false
     */
    public boolean isOutOfBounds(){
        return this.getY()>=World.HEIGHT; //炸弹的y>=窗口的高,即为越界了
    }

}


EnemyLife  接口

package cn.tedu.submarine;

/**
 * 命
 */
public interface EnemyLife {
    /**
     * 得命
     * @return 命数
     */
    public int getLife();
}


EnemyScore  得分

package cn.tedu.submarine;

/**
 * 分
 */
public interface EnemyScore {
    /**
     * 得分
     * @return 返回分数
     */
    public int getScore();
}

Images  照片

package cn.tedu.submarine;
import javax.swing.ImageIcon;
//图片位置:点项目名称,右键New Directory,命名为img,将图片粘贴到img中

/**
 * 图片类
 */
public class Images {
//  公开的  静态的   图片类型  变量名
    public static ImageIcon sea;
    public static ImageIcon gameover;
    public static ImageIcon battleship;
    public static ImageIcon obsersubm;
    public static ImageIcon torpesubm;
    public static ImageIcon minesubm;
    public static ImageIcon mine;
    public static ImageIcon bomb;

    static{ //初始化静态图片
        sea = new ImageIcon("img/sea.png"); //读取img下的sea.png到变量sea中
        gameover = new ImageIcon("img/gameover.png");
        battleship = new ImageIcon("img/battleship.png");
        obsersubm = new ImageIcon("img/obsersubm.png");
        torpesubm = new ImageIcon("img/torpesubm.png");
        minesubm = new ImageIcon("img/minesubm.png");
        mine = new ImageIcon("img/mine.png");
        bomb = new ImageIcon("img/bomb.png");
    }

    public static void main(String[] args) {
        //返回8表示图片读取成功,返回其余数字表示图片读取失败
        System.out.println(sea.getImageLoadStatus()); //8
        System.out.println(gameover.getImageLoadStatus());
        System.out.println(battleship.getImageLoadStatus());
        System.out.println(obsersubm.getImageLoadStatus());
        System.out.println(torpesubm.getImageLoadStatus());
        System.out.println(minesubm.getImageLoadStatus());
        System.out.println(mine.getImageLoadStatus());
        System.out.println(bomb.getImageLoadStatus());
    }
}

Mine  

package cn.tedu.submarine;

import javax.swing.*;

/**
 * 水雷类
 */
public class Mine extends SeaObject {
    /**
     * 构造方法
     * @param x 水雷的初始x坐标
     * @param y 水雷的初始y坐标
     */
    public Mine(int x,int y){ //因为水雷的初始坐标,是根据水雷潜艇的坐标计算出来的,所以不能写死
        super(11,11,x,y,1);
    }

    /**
     * 重写move()移动
     */
    public void move(){
        setY(getY()-getSpeed()); //y-(向上)
    }

    /**
     * 重写getImage()获取对象图片
     * @return 返回水雷图片
     */
    public ImageIcon getImage(){
        return Images.mine; //返回水雷图片
    }

    /**
     * 重写isOutOfBounds()检测水雷是否越界
     * @return 若越界则返回true,否则返回false
     */
    public boolean isOutOfBounds(){
        return this.getY()<=150-this.getHeight(); //水雷的y<=150-水雷的高,即为越界了
    }
}

MineSubmarine

package cn.tedu.submarine;

import javax.swing.*;

/**
 * 水雷潜艇类
 */
public class MineSubmarine extends SeaObject implements EnemyLife {
    /**
     * 构造方法
     */
    public MineSubmarine(){
        super(63,19);
    }

    /**
     * 重写move()移动
     */
    public void move(){
        setX(getX()+getSpeed()); //x+(向右)
    }

    /**
     * 重写getImage()获取对象图片
     * @return 返回水雷潜艇图片
     */
    public ImageIcon getImage(){
        return Images.minesubm; //返回水雷潜艇图片
    }

    /**
     * 发射水雷----生成水雷对象
     * @return 返回水雷对象
     */
    public Mine shootMine(){
        //x:水雷潜艇的x+水雷潜艇的宽
        //y:水雷潜艇的y-11
        return new Mine(this.getX()+this.getWidth(),this.getY()-11); //this指的是水雷潜艇
    }

    /**
     * 重写getLife()得命
     * @return 返回命数
     */
    public int getLife(){
        return 1; //打掉水雷潜艇,得1条命
    }
}


ObserveSubmarine

package cn.tedu.submarine;

import javax.swing.*;

/**
 * 侦察潜艇类
 */
public class ObserveSubmarine extends SeaObject implements EnemyScore {
    /**
     * 构造方法
     */
    public ObserveSubmarine(){
        super(63,19);
    }

    /**
     * 重写move()移动
     */
    public void move(){
        setX(getX()+getSpeed()); //x+(向右)
    }

    /**
     * 重写getImage()获取对象图片
     * @return 返回侦察潜艇图片
     */
    public ImageIcon getImage(){
        return Images.obsersubm; //返回侦察潜艇图片
    }

    /**
     * 重写getScore()得分
     * @return 返回分数
     */
    public int getScore(){
        return 10; //打掉侦察潜艇,得10分
    }
}


SeaObject

package cn.tedu.submarine;

import javax.swing.ImageIcon;
import java.awt.*;
import java.util.Random;

/**
 * 海洋对象类,是所有类的超类
 */
public abstract class SeaObject {
    /**
     * 活着的
     */
    public static final int LIVE = 0;
    /**
     * 死了的
     */
    public static final int DEAD = 1; //死了的
    private int state = LIVE; //当前状态(默认为活着的)

    private int width;  //宽
    private int height; //高
    private int x;      //x坐标
    private int y;      //y坐标
    private int speed;  //速度

    public int getState() {
        return state;
    }

    public void setState(int state) {
        this.state = state;
    }

    public int getWidth() {
        return width;
    }

    public void setWidth(int width) {
        this.width = width;
    }

    public int getHeight() {
        return height;
    }

    public void setHeight(int height) {
        this.height = height;
    }

    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 int getSpeed() {
        return speed;
    }

    public void setSpeed(int speed) {
        this.speed = speed;
    }

    //因为三种潜艇的width/height都是不一样的,所以数据不能写死,需传参写活
    //因为三种潜艇的x/y/speed代码都是一样的,所以数据可以写死,不需要传参
    /**
     * 专门给侦察潜艇、鱼雷潜艇、水雷潜艇提供的构造方法
     * @param width 潜艇的宽
     * @param height 潜艇的高
     */
    public SeaObject(int width,int height){
        this.width = width;
        this.height = height;
        x = -width;
        Random rand = new Random(); //创建随机数对象
        y = rand.nextInt(World.HEIGHT-height-150+1)+150; //150到(窗口高-潜艇高)之内随机生成
        speed = rand.nextInt(3)+1; //1到3之内随机生成
    }

    //因为三种对象的width/height/x/y/speed都是不一样的,所以数据不能写死,需传参写活
    /**
     * 专门给战舰、水雷、炸弹提供的构造方法
     * @param width 宽
     * @param height 高
     * @param x x坐标
     * @param y y坐标
     * @param speed 速度
     */
    public SeaObject(int width,int height,int x,int y,int speed){
        this.width = width;
        this.height = height;
        this.x = x;
        this.y = y;
        this.speed = speed;
    }

    /**
     * 移动
     */
    public abstract void move();

    /**
     * 获取对象的图片
     * @return 返回对象所对应的图片
     */
    public abstract ImageIcon getImage();

    /**
     * 判断对象是否是活着的
     * @return 返回true表示活着的,否则表示死了的
     */
    public boolean isLive(){
        return state==LIVE; //若state为LIVE,表示活着的,返回true,否则返回false
    }

    /**
     * 判断对象是否是死了的
     * @return 返回true表示死了的,否则表示活着的
     */
    public boolean isDead(){
        return state==DEAD; //若state为DEAD,表示死了的,返回true,否则返回false
    }

    /**
     * 画对象
     * @param g 画笔
     */
    public void paintImage(Graphics g){
        if(this.isLive()){ //若活着的
            this.getImage().paintIcon(null,g,this.x,this.y); //----不要求掌握
        }
    }

    /**
     * 检测潜艇是否越界
     * @return 若越界则返回true,否则返回false
     */
    public boolean isOutOfBounds(){
        return this.x>=World.WIDTH; //潜艇的x>=窗口的宽,即为越界了
    }

    /**
     * 检测碰撞
     * @param other 另一个对象  this表示一个对象
     * @return 若撞上了则返回true,否则返回false
     */
    public boolean isHit(SeaObject other){
        //假设:this为潜艇,other为炸弹
        int x1 = this.x-other.width;  //x1:潜艇的x-炸弹的宽
        int x2 = this.x+this.width;   //x2:潜艇的x+潜艇的宽
        int y1 = this.y-other.height; //y1:潜艇的y-炸弹的高
        int y2 = this.y+this.height;  //y2:潜艇的y+潜艇的高
        int x = other.x; //x:炸弹的x
        int y = other.y; //y:炸弹的y     //练习-----------2:34继续

        return x>=x1 && x<=x2
               &&
               y>=y1 && y<=y2; //x在x1与x2之间,并且,y在y1与y2之间,即为撞上了
    }

    /**
     * 海洋对象去死
     */
    public void goDead(){
        state = DEAD; //将当前状态修改为DEAD死了的
    }
}






TorpedoSubmarine

package cn.tedu.submarine;

import javax.swing.*;

/**
 * 鱼雷潜艇类
 */
public class TorpedoSubmarine extends SeaObject implements EnemyScore {
    /**
     * 构造方法
     */
    public TorpedoSubmarine(){
        super(64,20);
    }

    /**
     * 重写move()移动
     */
    public void move(){
        setX(getX()+getSpeed()); //x+(向右)
    }

    /**
     * 重写getImage()获取对象图片
     * @return 返回鱼雷潜艇图片
     */
    public ImageIcon getImage(){
        return Images.torpesubm; //返回鱼雷潜艇图片
    }

    /**
     * 重写getScore()得分
     * @return 返回分数
     */
    public int getScore(){
        return 40; //打掉鱼雷潜艇,得40分
    }
}


World  整个游戏窗口

package cn.tedu.submarine;
import javax.swing.JFrame;
import javax.swing.JPanel; //1.
import java.awt.Graphics;
import java.util.Arrays;
import java.util.Timer;
import java.util.TimerTask;
import java.util.Random;
import java.awt.event.KeyAdapter;
import java.awt.event.KeyEvent;

/**
 * 整个游戏窗口
 */
public class World extends JPanel { //2.
    /**
     * 窗口的宽
     */
    public static final int WIDTH = 641;
    /**
     * 窗口的高
     */
    public static final int HEIGHT = 479;

    /**
     * 运行状态
     */
    public static final int RUNNING = 0;
    /**
     * 暂停状态
     */
    public static final int PAUSE = 1;
    /**
     * 游戏结束状态
     */
    public static final int GAME_OVER = 2;
    private int state = RUNNING; //当前状态(默认为运行状态)

    //如下这一堆对象就是窗口中你所看到的对象
    private Battleship ship = new Battleship(); //战舰对象
    private SeaObject[] submarines = {}; //潜艇数组
    private Mine[] mines = {}; //水雷数组
    private Bomb[] bombs = {}; //炸弹数组

    /**
     * 生成潜艇(侦察潜艇、鱼雷潜艇、水雷潜艇)对象
     * @return 返回潜艇
     */
    private SeaObject nextSubmarine(){
        Random rand = new Random(); //随机数对象
        int type = rand.nextInt(20); //0到19之间
        if(type<10){ //0到9时,返回侦察潜艇对象
            return new ObserveSubmarine();
        }else if(type<16){ //10到15时,返回鱼雷潜艇对象
            return new TorpedoSubmarine();
        }else{ //16到19时,返回水雷潜艇对象
            return new MineSubmarine();
        }
    }

    private int subEnterIndex = 0; //潜艇入场计数
    /**
     * 潜艇入场
     */
    private void submarineEnterAction(){ //每10毫秒走一次
        subEnterIndex++; //每10毫秒增1
        if(subEnterIndex%40==0){ //每400(40*10)毫秒走一次
            SeaObject obj = nextSubmarine(); //获取潜艇对象
            submarines = Arrays.copyOf(submarines,submarines.length+1); //扩容
            submarines[submarines.length-1] = obj; //将obj添加到submarines最后一个元素上
        }
    }

    private int mineEnterIndex = 0; //水雷入场计数
    /**
     * 水雷入场
     */
    private void mineEnterAction(){ //每10毫秒走一次
        mineEnterIndex++; //每10毫秒增1
        if(mineEnterIndex%100==0){ //每1000(100*10)毫秒走一次
            for(int i=0;i

 

【潜艇游戏开发】最全的源代码_第1张图片 

 

 

 

【潜艇游戏开发】最全的源代码_第2张图片 

 

 

点关注、不迷路

你可能感兴趣的:(JAVA编程,java,jvm,servlet)