JSD-2204-面向对象-多态-潜艇游戏--Day15

本文介绍了Java游戏潜艇大战中如何利用多态实现水雷入场、潜艇与炸弹碰撞检测以及分数和生命值的更新。详细讲解了多态的概念,包括对象的多态性和行为的多态性,并阐述了向上造型和强制类型转换的使用。游戏的关键类如Battleship、Bomb、接口如EnemyLife和EnemyScore等都在文章中进行了说明。
摘要由CSDN通过智能技术生成

1.多态

   - 意义:

     - 同一个对象被造型为不同的类型时,有不同的功能

       ----对象的多态:我、你、水......-------------所有对象都是多态的(明天总结时详细讨论)

     - 同一类型的引用在指向不同的对象时,有不同的实现

       ----行为的多态:cut()、getImage()、move()......-----所有抽象方法都是多态的

   - 向上造型/自动类型转换:

     - 超类型的引用指向派生类的对象
     - 能点出来什么,看引用的类型
     - 能造型成为的类型有:超类+所实现的接口

   - 强制类型转换,成功的条件只有如下两种:

     - 引用所指向的对象,就是该类型
     - 引用所指向的对象,实现了该接口或继承了该类

   - 强转时若不符合如上两个条件,则发生ClassCastException类型转换异常

     建议:在强转之前先通过instanceof判断引用的对象是否是该类型

     > 何时强转:当你想访问的东西超类中没有,就需要强转(哪个类中有就转成哪个类型)

   public class MultiTypeDemo {
       public static void main(String[] args) {
           Aoo o = new Boo();
           Boo o1 = (Boo)o; //引用o所指向的对象就是Boo类型
           Inter o2 = (Inter)o; //引用o所指向的对象实现了Inter接口
           //Coo o3 = (Coo)o; //运行时发生ClassCastException类型转换异常
           if(o instanceof Coo){ //false
               Coo o4 = (Coo)o;
           }else{
               System.out.println("o不是Coo类型");
           }
       }
   }
   
   interface Inter{
   }
   class Aoo{
   }
   class Boo extends Aoo implements Inter{
   }
   class Coo extends Aoo{
   }

2. 潜艇游戏第九天:

1. 水雷入场:-------后半段

   - 水雷对象是由水雷潜艇发射出来的,所以在MineSubmarine中设计shootMine()生成水雷对象

   - 水雷入场为定时发生的,所以在run中调用mineEnterAction()实现水雷入场

     在mineEnterAction()中:

     ​    每1000毫秒,遍历潜艇数组,判断若是水雷潜艇,则强转为水雷潜艇类型,

     ​    获取水雷对象obj,mines扩容,将obj添加到mines最后一个元素上

2. 炸弹与潜艇的碰撞:

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

     在Battleship中设计addLife()增命

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

     在bombBangAction()中:

     ​    遍历所有炸弹得炸弹,遍历所有潜艇得潜艇,判断若都活着并且还撞上了:

     ​        潜艇去死、炸弹去死

     ​        判断若潜艇能得分,则强转为得分接口,增分

     ​                若潜艇能得命,则强转为得命接口,获取命数,战舰增命

3. 画分和画命:
   - 在Battleship中设计getLife()获取命数
   - 在World类的paint中: 画分和画命

2.1目录

2.1.1Battleship类

package cn.tedu.submarine;

import javax.swing.*;
import java.awt.Graphics;
import java.util.Arrays;
import java.util.Random;
import java.util.Timer;
import java.util.TimerTask;
import java.awt.event.KeyAdapter;
import java.awt.event.KeyEvent;

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



    private Battleship ship = new Battleship();//战舰
    private SeaObject[] submarines = {};//潜艇数组(侦察潜艇,鱼雷潜艇,水雷潜艇)
    private Mine[] mines = {};//水雷数组
    private Bomb[] bombs = {};//炸弹数组

    //玩家得分
    private int score = 0;

    public void action() {
        KeyAdapter k = new KeyAdapter() {
            /**
             * 按键按下事件
             * @param e
             */
            @Override
            public void keyPressed(KeyEvent e) {
                //判断按的是不是空格键


                if (e.getKeyCode() == KeyEvent.VK_LEFT){
                    ship.moveLeft();
                }

                if (e.getKeyCode() == KeyEvent.VK_RIGHT){
                    ship.moveRight();
                }
            }

            /**
             * 重写keyReleased()按键抬起事件
             * @param e
             */
            @Override
            public void keyReleased(KeyEvent e) {
                if (e.getKeyCode()==KeyEvent.VK_SPACE){
                    Bomb bomb = ship.shootBomb();
                    bombs = Arrays.copyOf(bombs,bombs.length+1);
                    bombs[bombs.length-1] = bomb;
                }
            }
        };
        this.addKeyListener(k);//添加键盘的侦听器



        Timer timer = new Timer();
        int interval = 10;
        timer.schedule(new TimerTask() {
            @Override
            public void run() {
                submarineEnterAction();//敌人入场
                minesEnterAction();//水雷入场
                submarineMove();//潜艇移动
                imageChuJie();//判断图片出界删除
                bombBangAction();//炸弹碰撞潜艇
                mineBangAction();//
                repaint();//重新画一下
            }
        }, interval, interval);
    }

    public void mineBangAction() {
        for (int i = 0; i < mines.length; i++) {
            Mine m = mines[i];
            if (m.isLive() && ship.isLive() && m.isHit(ship)){
                int life = ship.getLife();
                life--;
                ship.setLife(life);
            }
        }
    }

    /**
     * 物块碰撞
     */
    public void bombBangAction() {
        //遍历所有炸弹
        for (int i = 0; i < bombs.length; i++) {
            Bomb b = bombs[i];
            for (int j = 0; j < submarines.length; j++) {
                SeaObject s = submarines[j];
                //若都或者并且还撞上了
                if(b.isLive() && s.isLive() && s.isHit(b)){
                    s.goDead();//潜艇去死
                    b.goDead();//炸弹去死
                    //判断是不是加分的
                    if (s instanceof EnemyScore){
                        score+=((EnemyScore) s).getScore();
                    }
                    //判断是不是加命的
                    if (s instanceof EnemyLife){
                        int num = ((EnemyLife) s).getLife();
                        ship.addLife(num);
                    }
                }
            }
        }
    }

    /**
     * 图片出界删除方法
     */
    public void imageChuJie() {
        for (int i = 0; i < submarines.length; i++) {
            if (submarines[i].x>WIDTH||submarines[i].isDeal()){
                submarines[i] = submarines[submarines.length-1];
                submarines = Arrays.copyOf(submarines,submarines.length-1);
            }
        }
        for (int i = 0; i < bombs.length; i++) {
            if (bombs[i].y>HEIGHT||bombs[i].isDeal()){
                bombs[i] = bombs[bombs.length-1];
                bombs = Arrays.copyOf(bombs,bombs.length-1);
            }
        }
        for (int i = 0; i < mines.length; i++) {
            if (mines[i].y<150||mines[i].isDeal()){
                mines[i] = mines[mines.length-1];
                mines = Arrays.copyOf(mines,mines.length-1);
            }
        }
    }

    /**
     * 潜艇移动
     */
    public void submarineMove() {
        for (int i = 0; i < submarines.length; i++) {
            submarines[i].move();
        }

        for (int i = 0; i < bombs.length; i++) {
            bombs[i].move();
        }

        for (int i = 0; i < mines.length; i++) {
            mines[i].move();
        }
    }

    private int mineEnterIndex = 0;//水雷入场计数
    /**
     * 水雷入场
     */
    public void minesEnterAction() {//没10个毫秒走一次
        mineEnterIndex++;//没10毫秒增1
        if (mineEnterIndex % 100 == 0){
            for (int i = 0; i < submarines.length; i++) {
                if (submarines[i] instanceof MineSubmarine){
                    MineSubmarine ms = (MineSubmarine)submarines[i];
                    Mine mine = ms.shootMine();
                    mines = Arrays.copyOf(mines,mines.length+1);
                    mines[mines.length-1] = mine;
                }
            }
        }
    }


    private int subEnterIndex = 0;
    /**
     * 敌人入场
     */
    public void submarineEnterAction() {
        subEnterIndex++;
        if (subEnterIndex%40 == 0){
            SeaObject obj = nextSubmarine();
            submarines = Arrays.copyOf(submarines,submarines.length+1);
            submarines[submarines.length-1]=obj;
        }
    }

    /**
     * 生成潜艇对象
     */
    public SeaObject nextSubmarine() {
        Random random = new Random();
        int type = random.nextInt(20);
        if (type < 10) {
            return new ObserverSubmarine();
        } else if (type < 15) {
            return new TorpedoSubmarine();
        } else {
            return new MineSubmarine();
        }
    }


    /**
     * 重写JPanel中的paint()画  g 画笔
     *
     * @param g
     */
    @Override
    public void paint(Graphics g) {
        Images.sea.paintIcon(null, g, 0, 0);//海洋图片
        ship.paintImage(g);
        //画敌人
        for (int i = 0; i < submarines.length; i++) {
            submarines[i].paintImage(g);
        }
        //画水雷
        for (int i = 0; i < mines.length; i++) {
            mines[i].paintImage(g);
        }
        //画炸弹
        for (int i = 0; i < bombs.length; i++) {
            bombs[i].paintImage(g);
        }
        g.drawString("SCORE:"+score,10,25);
        g.drawString("LIFE:"+ship.getLife(),10,45);
    }

    public static void main(String[] args) {
        JFrame frame = new JFrame();
        World world = new World();
        world.setFocusable(true);
        frame.add(world);
        frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
        frame.setSize(WIDTH + 16, HEIGHT + 39);
        frame.setLocationRelativeTo(null);
        frame.setVisible(true);

        world.action();


    }


}

2.1.2Bomb类

package cn.tedu.submarine;

import javax.swing.*;
import java.util.Objects;

/**
 * 炸弹
 */
public class Bomb extends SeaObject{

    public Bomb(int x , int y) {
        super(9,12,x,y,3);
    }


    /**
     * 炸弹移动的方法
     */
    @Override
    public void move() {
        y += speed;
    }

    @Override
    public ImageIcon getImage() {
        return Images.bomb;
    }


}

2.1.3EnemyLife接口

package cn.tedu.submarine;

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

2.1.4EnemyScore接口

package cn.tedu.submarine;

public interface EnemyScore {
    int getScore();
}

2.1.5Images类

package cn.tedu.submarine;

import javax.swing.ImageIcon;


public class Images {
    /**
     * 背景图
     */
    public static ImageIcon sea;
    /**
     * 战舰图
     */
    public static ImageIcon battleship;
    /**
     * 炸弹图片
     */
    public static ImageIcon bomb;
    /**
     * 游戏结束
     */
    public static ImageIcon gameover;
    /**
     * 水雷图片
     */
    public static ImageIcon mine;
    /**
     * 水雷潜艇
     */
    public static ImageIcon minesubm;
    /**
     * 侦察潜艇
     */
    public static ImageIcon obsersubm;
    /**
     * 鱼类潜艇
     */
    public static ImageIcon torpesubm;

    /**
     * 初始化图片
     */
    static {
        battleship = new ImageIcon("img/battleship.png");
        sea = new ImageIcon("img/sea.png");
        bomb = new ImageIcon("img/bomb.png");
        gameover = new ImageIcon("img/gameover.png");
        mine = new ImageIcon("img/mine.png");
        minesubm = new ImageIcon("img/minesubm.png");
        obsersubm = new ImageIcon("img/obsersubm.png");
        torpesubm = new ImageIcon("img/torpesubm.png");
    }

//    /**
//     * 测试图片
//     * @param args
//     */
//    public static void main(String[] args) {
//        //返回8表示成功了
//        System.out.println(battleship.getImageLoadStatus());
//    }

}

2.1.6Mine类

package cn.tedu.submarine;

import javax.swing.*;
import java.util.Objects;

/**
 * 水雷
 */
public class Mine extends SeaObject{

    public Mine(int x , int y) {
        super(11,11,x,y,1);
    }


    /**
     * 水雷移动的方法
     */
    @Override
    public void move() {
        y-=speed;
    }

    @Override
    public ImageIcon getImage() {
        return Images.mine;
    }


}

2.1.7MineSubMarine类

package cn.tedu.submarine;

import javax.swing.*;
import java.util.Objects;
import java.util.Random;

/**
 * 水雷潜艇
 */
public class MineSubmarine extends SeaObject implements EnemyLife{


    public MineSubmarine() {
        super(63,19);
    }


    /**
     * 水雷潜艇移动
     */
    @Override
    public void move() {
        x+=speed;
    }

    @Override
    public ImageIcon getImage() {
        return Images.minesubm;
    }

    /**
     * 发射水雷---生成水雷对象
     * @return
     */
    public Mine shootMine(){
        return new Mine(this.x+this.width,this.y-11);
    }

    @Override
    public int getLife() {
        return 1;
    }
}

2.1.8ObserverSubMarine类

package cn.tedu.submarine;

import javax.swing.*;
import java.util.Objects;
import java.util.Random;

/**
 * 侦察潜艇
 */
public class ObserverSubmarine extends SeaObject implements EnemyScore{


    public ObserverSubmarine() {
        super(63,19);
    }


    /**
     * 侦察潜艇移动
     */
    @Override
    public void move() {
        x+=speed;
    }


    @Override
    public ImageIcon getImage() {
        return Images.obsersubm;
    }


    @Override
    public int getScore() {
        return 10;
    }
}

2.1.9SeaObject类

package cn.tedu.submarine;

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

/**
 * 海洋对象
 */
public abstract class SeaObject {
    public static final int LIVE = 0;//或者的
    public static final int DEAL = 1;//死了的
    protected int state = LIVE;//当前状态(默认是活着的)
    /**
     * 成员变量一般都要private的
     * 此处设计为protected
     * 因为还没有讲到getter/setter
     */
    /**
     * 宽
     */
    protected int width;
    /**
     * 高
     */
    protected int height;
    /**
     * x轴
     */
    protected int x;
    /**
     * y轴
     */
    protected int y;
    /**
     * 速度
     */
    protected int 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 SeaObject(int width,int height){
        this.width = width;
        this.height = height;
        Random rand = new Random();
        x = -width;
        y = rand.nextInt(World.HEIGHT-height-150+1 ) +150;
        this.speed = rand.nextInt(3)+1;
    }

    /**
     * 移动的方法
     */
    public abstract void move();

    /**
     * 获取对象的图片
     */
    public abstract ImageIcon getImage();

    /**
     * 判断是活着的
     * @return
     */
    public boolean isLive(){
        return state == LIVE;
    }

    /**
     * 判断是死的吗
     * @return
     */
    public boolean isDeal(){
        return  state == DEAL;
    }

    /**
     * 画图片
     * @param g
     */
    public void paintImage(Graphics g){
        if (isLive()){//若或者的
            //不要求掌握
            this.getImage().paintIcon(null,g,this.x,this.y);
        }
    }

    /**
     * 检测碰撞的算法
     * @param other
     * @return
     */
    public boolean isHit(SeaObject other){
        int x1 = this.x-other.width;
        int x2 = this.x+this.width;
        int y1 = this.y-other.height;
        int y2 = this.y+this.height;
        int x = other.x;
        int y = other.y;
        return x>=x1 && x<=x2 && y>=y1 && y<=y2;
    }

    public void goDead(){
        state =DEAL;//将当前装填修改为DEAD死了的
    }
}

2.1.10TorpedoSubmarine类

package cn.tedu.submarine;

import javax.swing.*;
import java.util.Objects;
import java.util.Random;

/**
 * 鱼类潜艇
 */
public class TorpedoSubmarine extends SeaObject implements EnemyScore{


    public TorpedoSubmarine() {
        super(64,20);
    }


    /**
     * 鱼类潜艇移动的方法
     */
    @Override
    public void move() {
        x+=speed;
    }

    @Override
    public ImageIcon getImage() {
        return Images.torpesubm;
    }

    @Override
    public int getScore() {
        return 40;
    }
}

2.1.11World(测试类)

package cn.tedu.submarine;

import javax.swing.*;
import java.util.Objects;
import java.util.Random;

/**
 * 侦察潜艇
 */
public class ObserverSubmarine extends SeaObject implements EnemyScore{


    public ObserverSubmarine() {
        super(63,19);
    }


    /**
     * 侦察潜艇移动
     */
    @Override
    public void move() {
        x+=speed;
    }


    @Override
    public ImageIcon getImage() {
        return Images.obsersubm;
    }


    @Override
    public int getScore() {
        return 10;
    }
}

3.补充

3.1体会接口的好处:

   //复用性好、扩展性好、维护性好------------------高质量代码
   //被撞的是ObserveSubmarine-----调用ObserveSubmarine的getScore()-----10分
   //被撞的是TorpedoSubmarine-----调用TorpedoSubmarine的getScore()-----40分
   //被撞的是NuclearSubmarine-----调用NuclearSubmarine的getScore()-----80分
   if(s instanceof EnemyScore){ //------适用于所有实现EnemyScore接口的
       EnemyScore es = (EnemyScore)s;
       score += es.getScore();
   }
   //被撞的是MineSubmarine--------调用MineSubmarine的getLife()---------1
   //被撞的是NuclearSubmarine-----调用NuclearSubmarine的getLife()------3
   if(s instanceof EnemyLife){ //-------适用于所有实现EnemyLife接口的
       EnemyLife el = (EnemyLife)s;
       int num = el.getLife();
       ship.addLife(num);
   }
                                         
   //复用性差、扩展性差、维护性差------------------垃圾代码
   if(s instanceof ObserveSubmarine){ //---------只能适用于ObserveSubmarine的
       ObserveSubmarine os = (ObserveSubmarine)s;
       score += os.getScore();
   }
   if(s instanceof TorpedoSubmarine){ //---------只能适用于TorpedoSubmarine的
       TorpedoSubmarine ts = (TorpedoSubmarine)s;
       score += ts.getScore();
   }      
   if(s instanceof MineSubmarine){    //---------只能适用于MineSubmarine的
       MineSubmarine ms = (MineSubmarine)s;
       int num = ms.getLife();
       ship.addLife(num);
   }
   if(s instanceof NuclearSubmarine){ //---------只能适用于NuclearSubmarine
       NuclearSubmarine ns = (NuclearSubmarine)s;
       score += ns.getScore();
       int num = ns.getLife();
       ship.addLife(num);
   }

3.2碰撞检测图:

 

3.3明日单词:

   1)subtract:减
   2)gameover:结束
   3)running:运行

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值