Java学习二(飞机大战项目)day09

day09

1.子弹与敌人的碰撞
    1)在超类中FlyingObject设计hit()实现敌人与子弹/英雄机得碰撞

    /** 成员方法:检测敌人与子弹/英雄机的碰撞
     *  this:敌人    other:子弹 */
    public boolean hit(FlyingObject 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;
    }

    在超类中FlyingObject设计goDead()实现飞行物去死的

    /** 成员方法:飞行物去死 */
    public void goDead() {
        state = DEAD;    //将当前状态修改为DEAD
    }
import java.util.Random;
import java.awt.image.BufferedImage;
import javax.imageio.ImageIO;
import java.awt.Graphics;
/**
 * 飞行物--超类
 * @author soft01
 */
public abstract class FlyingObject {
    /** 常量: 三种状态(活着的、死了的、删除的)    */
    public static final int LIFE = 0;
    public static final int DEAD = 1;
    public static final int REMOVE = 2;

    /** 成员变量:当前状态(默认为活着的) */
    protected int state = LIFE;    

    /** 成员变量:宽、高、x轴、y轴 */
    protected int width;
    protected int height;
    protected int x;
    protected int y;                

    /** 构造方法:专门给英雄机、天空、子弹用 */
    public FlyingObject(int width,int height,int x,int y) {
        this.width = width;
        this.height = height;
        this.x = x;
        this.y = y;
    }

    /** 构造方法:专门给小敌机、大敌机、小蜜蜂用 */
    public FlyingObject(int width,int height) {
        this.width = width;
        this.height = height;
        Random rand = new Random();
        x = rand.nextInt(World.WIDTH-width);
        y = -height;
    }

    /**    抽象方法:飞行物移动        */
    public abstract void step();

    /**    抽象方法:获取图片        */
    public abstract BufferedImage getImage();

    /** 抽象方法:检查飞行物是否越界 */
    public abstract boolean outOfBounds();

    /** 静态方法:读取图片 */
    public static BufferedImage loadImage(String fileName) {
        try {
            BufferedImage img = ImageIO.read(FlyingObject.class.getResource(fileName));    //同包中读图片
            return img;
        } catch (Exception e) {
            e.printStackTrace();
            throw new RuntimeException();
        }
    }

    /** 成员方法:判断状态(活着的、死了的、删除的) */
    public boolean isLife() {
        return state == LIFE;
    }
    public boolean isDead() {
        return state == DEAD;
    }
    public boolean isRemove() {
        return state == REMOVE;
    }

    /** 成员方法:画对象的 g:画笔 */
    public void paintObject(Graphics g) {
        g.drawImage(getImage(),x,y,null);
    }

    /** 成员方法:检测敌人与子弹/英雄机的碰撞
     *  this:敌人    other:子弹 */
    public boolean hit(FlyingObject other) {
        int x1 = this.x - other.width;        //敌人的x - 子弹/英雄机的宽
        int x2 = this.x + this.width;        //敌人的x + 敌人的宽
        int y1 = this.y - other.height;    //敌人的y - 子弹/英雄机的高
        int y2 = this.y + this.height;        //敌人的y + 敌人的高
        int x = other.x;                                //子弹/英雄机的x
        int y = other.y;                                //子弹/英雄机的y
        return x>=x1 && x<=x2 && y>=y1 && y<=y2;    //x在x1和x2之间,y在y1和y2之间
    }

    /** 成员方法:飞行物去死 */
    public void goDead() {
        state = DEAD;        //将当前状态修改为DEAD
    }
}
    在Hero类中设计addLife()增命、addDoubleFire()增火力

    /**    成员方法:命数增加    */
    public void addLife() {
        life++;    //命数增1
    }

    /**    成员方法:火力值增加        */
    public void addDoubleFire() {
        doubleFire += 40;        //火力值增40
    }
import java.awt.image.BufferedImage;

/**
 * 英雄机
 * @author soft01
 */
public class Hero extends FlyingObject{
    /** 静态变量:英雄机图片    */
    private static BufferedImage[] images;
    static {
        images = new BufferedImage[2];
        for (int i = 0; i < images.length; i++) {
            images[i] = loadImage("hero" + i + ".png");
        }
    }

    /**    成员变量:生命、火力值    */
    private int life;        //生命
    private int doubleFire;        //火力值

    /**    构造方法    */
    public Hero(){
        super(97,124,140,400);
        life = 3;
        doubleFire = 0;
    }

    /**    成员方法:命数增加    */
    public void addLife() {
        life++;    //命数增1
    }

    /**    成员方法:获取命数    */
    public int getLife() {
        return life;    //返回命
    }

    /**    成员方法:火力值增加        */
    public void addDoubleFire() {
        doubleFire += 40;        //火力值增40
    }

    /**    成员方法:英雄机移动        */
    public void step() {}

    /**    成员方法:英雄机随鼠标移动x,y    */
    public void moveTo(int x,int y) {
        this.x = x - this.width/2;        //英雄机的x=鼠标的x-1/2英雄机的宽
        this.y = y - this.height/2;    //英雄机的y=鼠标的y-1/2英雄机的高
    }

    /**    成员方法:获取图片    */
    int index = 0;
    @Override
    public BufferedImage getImage() {
        if(isLife()) {
            return images[index++%2];        //(index++%2)余数为0或1
        }
        return null;
    }

    /**    成员方法:英雄机发射子弹(创建子弹对象)    */
    public Bullet[] shoot() {
        int xStep = this.width/4;    //xStep:1/4英雄机的宽
        int yStep = 20;            //yStep:固定的20
        if (doubleFire > 0) {        //双
            Bullet[] bs = new Bullet[2];        //2发子弹
            //英雄机的x坐标加1/4英雄机的宽
        bs[0] = new Bullet(this.x + 1 * xStep,y-yStep);
            //英雄机的x坐标加3/4英雄机的宽
        bs[1] = new Bullet(this.x + 3 * xStep, y-yStep);
            doubleFire -= 2;    //发射一次双倍火力,火力值减2
            return bs;
        } else {                    //单
            Bullet[] bs = new Bullet[1];        //1发子弹
        //英雄机的x坐标加2/4英雄机的宽
        bs[0] = new Bullet(this.x + 2 * xStep, y-yStep);
            return bs;
        }
    }

    /**    成员方法:英雄机永不越界    */
    @Override
    public boolean outOfBounds() {
        return false;
    }
}
  2)子弹与敌人的碰撞为定时发生的,所以在run()中调用BulletBangAction()方法
在BulletBangAction()中:
遍历所有子弹,获取每一个子弹,遍历所有敌人,获取每个敌人
判断是否撞上了,若撞上了:
    1)子弹去死,敌人去死
    2)小敌机和大敌机 ----------得分
       小蜜蜂 ----------------英雄机得命或双倍火力

/** 成员方法:子弹与敌人的碰撞 */
int score = 0;
public void bulletBangAction() {    //每10个毫秒走一次
    //遍历子弹数组
    for (int i = 0; i < bullets.length; i++) {
        Bullet b = bullets[i];//得到每一个子弹
        //遍历敌人数组
        for (int j = 0; j < enemies.length; j++) {
            FlyingObject f = enemies[j];    //得到每一个敌人
            //如果活着的子弹和活着的敌人撞上了
            if(b.isLife() && f.isLife() && f.hit(b)) {
                b.goDead();            //子弹去死
                f.goDead();            //敌人去死
                if (f instanceof Enemy) {//若被撞对象是敌人
                    Enemy e = (Enemy)f;//强转为得分接口
                    score += e.getScore();//玩家得分
                }
                if (f instanceof Award) {//若被撞对象是奖励
                  Award a = (Award)f;//    强转为奖励接口
                  int type = a.getType();//获取奖励类型                      //基于不同的类型来得到不同的奖励
                  switch (type) {
                  //若奖励为火力值
                  case Award.DOUBLE_FIRE:
                    hero.addDoubleFire();    //则增加火力值
                    break;
                    case Award.LIFE:        //若奖励为命
                    hero.addLife();        //则增加命
                    break;                                              }
                }
            }
        }
    }
}

2.画分和画命
    1)在Hero类中设计getLife()获取命

    /**    成员方法:获取命数    */
    public int getLife() {
        return life;    //返回命
    }

    2)在paint()方法中,画分和画命

    g.drawString("SCORE:" + score,10,25);
    g.drawString("LIFE:" + hero.getLife(), 10, 45);
import java.awt.Graphics;
import javax.swing.JFrame;
import javax.swing.JPanel;
import java.util.Timer;
import java.util.TimerTask;
import java.util.Random;
import java.util.Arrays;
import java.awt.event.MouseAdapter;
import java.awt.event.MouseEvent;;

/**
 * 整个世界
 * @author soft01
 */
public class World extends JPanel{
    /** 常量:窗口宽、窗口高 */
    public static final int WIDTH = 400;
    public static final int HEIGHT = 700;

    /**    成员变量:天空、英雄机、飞行物敌人数组、子弹数组    */
    private Sky sky = new Sky();
    private Hero hero = new Hero();
    private FlyingObject[] enemies = {};
    private Bullet[] bullets = {};        

    /**    启动程序的执行    */
    public void action() {
        Timer timer = new Timer();                                    //创建定时器对象
        int interval = 10;                                                //定时间隔(以毫秒为单位)
        timer.schedule(new TimerTask() {                        //匿名内部类
            @Override
            public void run() {                                            //定时干的事(每10个毫秒走一次)
                enterAction();                                                //敌人入场,子弹入场,飞行物移动
                shootAction();                                                //子弹入场,英雄机发射子弹
                stepAction();                                                    //飞行物入场
                outOfBoundsAction();                                    //删除越界
                bulletBangAction();                                        //子弹与敌人的碰撞
                repaint();                                                     //重画(重新调用paint()方法)
            }
        },interval,interval);                                            //定时计划

        /** 鼠标侦听器 */
        MouseAdapter l = new MouseAdapter() {
            /** 重写mouseMoved()鼠标移动 */
            public void mouseMoved(MouseEvent e) {
                int x = e.getX();        //获取鼠标的x坐标
                int y = e.getY();        //获取鼠标的y坐标
                hero.moveTo(x, y);    //英雄机随着鼠标移动
            }
        };
        this.addMouseListener(l);                //处理鼠标操作事件
        this.addMouseMotionListener(l);    //处理鼠标滑动事件
    }

    /** 成员方法:生成敌人(小敌机、大敌机、小蜜蜂)对象 */
    public FlyingObject nextOne() {
        Random rand = new Random();    //随机数对象
        int type = rand.nextInt(20);    //0~19之间的数
        if (type < 11) {                            //0~7返回小敌机
            return new Airplane();
        } else if(type < 17){                //8~15返回小敌机
            return new BigAirplane();
        } else {                                        //16~19返回小敌机
            return new Bee();
        }
    }

    /** 成员方法:敌人(小敌机、大敌机、小蜜蜂)入场 */
    int enterIndex = 0;                            //敌人入场计数
    public void enterAction() {            //每10个毫秒走一次
        enterIndex++;                                    //每10毫秒增1
        if(enterIndex%40 == 0) {            //每400(10*40)毫秒走一次
            FlyingObject obj = nextOne();
            enemies = Arrays.copyOf(enemies, enemies.length+1);    //数组扩容
            enemies[enemies.length-1] = obj;                //将敌人对象填充到enemies数组的最后一个元素上
        }
    }

    /** 成员方法:子弹入场,英雄机发射子弹 */
    int shootIndex = 0;                            //子弹入场计数
    public void shootAction() {            //每10个毫秒走一次
        shootIndex++;                                    //每10毫秒增1
        if(shootIndex%20 == 0) {            //每300(10*30)毫秒走一次
            Bullet[] bs = hero.shoot();    //获取英雄机发射出来的子弹对象
            bullets = Arrays.copyOf(bullets, bullets.length+bs.length);    //扩容(bs有几个元素就扩大几个)
            System.arraycopy(bs, 0, bullets, bullets.length - bs.length, bs.length);     //数组的追加
        }
    }

    /** 成员方法:飞行物入场 */
    public void stepAction() {
        sky.step();                    //天空移动
        for (int i = 0; i < enemies.length; i++) {
            enemies[i].step();    //飞行物移动
        }
        for (int i = 0; i < bullets.length; i++) {
            bullets[i].step();    //子弹移动
        }
    }

    /** 成员方法:删除越界 */
    public void outOfBoundsAction() {    //每10个毫秒走一次
        int index = 0;        //1)不越界敌人下标    2)不越界敌人个数
        FlyingObject[] enemyLives = new FlyingObject[enemies.length];     //不越界敌人数组
        for (int i = 0; i < enemies.length; i++) {    //获取敌人数组
            FlyingObject f = enemies[i];        //获取每一个敌人
            if(!f.outOfBounds()) {    //不越界
                enemyLives[index] = f;    //将不越界敌人放到不越界数组中
                index++;        //1)不越界敌人数组下标增一        2)不越界敌人个数增1
            }
        }
        enemies = Arrays.copyOf(enemyLives, index);    //将不越界数组中的元素复制到敌人数组之中,数组的长度为index

        index = 0;
        Bullet[] bulletLives = new Bullet[bullets.length];
        for (int i = 0; i < bullets.length; i++) {
            Bullet b = bullets[i];
            if(!b.outOfBounds()) {
                bulletLives[index] = b;
                index++;
            }
        }
        bullets = Arrays.copyOf(bulletLives, index);
    }

    /** 成员方法:子弹与敌人的碰撞 */
    int score = 0;
    public void bulletBangAction() {                                        //每10个毫秒走一次
        for (int i = 0; i < bullets.length; i++) {                //遍历子弹数组
            Bullet b = bullets[i];                                                //得到每一个子弹
            for (int j = 0; j < enemies.length; j++) {            //遍历敌人数组
                FlyingObject f = enemies[j];                                    //得到每一个敌人
                if(b.isLife() && f.isLife() && f.hit(b)) {        //如果活着的子弹和活着的敌人撞上了
                    b.goDead();                                                            //子弹去死
                    f.goDead();                                                            //敌人去死
                    if (f instanceof Enemy) {                                    //若被撞对象是敌人
                        Enemy e = (Enemy)f;                                            //强转为得分接口
                        score += e.getScore();                                    //玩家得分
                    }
                    if (f instanceof Award) {                                    //    若被撞对象是奖励
                        Award a = (Award)f;                                            //    强转为奖励接口
                        int type = a.getType();                                    //获取奖励类型
                        switch (type) {                                                    //基于不同的类型来得到不同的奖励
                        case Award.DOUBLE_FIRE:                                    //若奖励为火力值
                            hero.addDoubleFire();                                    //则增加火力值
                            break;
                        case Award.LIFE:                                                //若奖励为命
                            hero.addLife();                                                //则增加命
                            break;
                        }
                    }
                }
            }
        }
    }

    /** 成员方法:paint()方法 */
    @Override
    public void paint(Graphics g) {
        sky.paintObject(g);                                                //画天空
        hero.paintObject(g);                                            //画英雄机
        for (int i = 0; i < enemies.length; i++) {    //遍历所有敌人
            enemies[i].paintObject(g);                                //画敌对飞行物
        }
        for (int i = 0; i < bullets.length; i++) {    //遍历子弹
            bullets[i].paintObject(g);                                //画子弹
        }
        g.drawString("SCORE:" + score,10,25);
        g.drawString("LIFE:" + hero.getLife(), 10, 45);
    }

    /** main主方法 */
    public static void main(String[] args) {
        JFrame frame = new JFrame();                                                    //创建窗口
        World world = new World();                                                        //创建面板
        frame.add(world);                                                                        //将面板添加到窗口

        frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);    //设置关闭窗口即停止运行程序
        frame.setSize(WIDTH,HEIGHT);                                                    //设置窗口大小
        frame.setLocationRelativeTo(null);                                     //设置窗口居中显示
        frame.setVisible(true);                                                         //1)设置窗口可见        2)尽快调用paint()方法

        world.action();                                                                            //启动程序
    }

}

 

原文地址:https://www.cnblogs.com/lj-6112/p/8666539.html

时间: 2024-10-29 05:42:50

Java学习二(飞机大战项目)day09的相关文章

飞机大战项目

学习python的一个小项目项目名称:飞机大战项目项目语言:python实现功能:飞机连续发射三个子弹,打中敌机,敌机销毁,飞机碰到敌机,飞机销毁,游戏结束 import pygame from plane_sprites import * class PlaneGame(object): '''飞机大战主游戏''' def __init__(self): print("游戏初始化") # 1,创建游戏的窗口 self.screen = pygame.display.set_mode(

Java学习:二 基础

2014 - 5 - 22 上午 Java对大小写敏感. 点号(.)用于调用方法,Java的能用语法是: object.method(parameters); Java中的常量声明使用final关键字.且仅能赋值一次.习惯上,常量名大写. 可使用static final 定义一个类常量,以便在一个类中的多个方法中使用. 类常量定义在main方法外部,以便同一类其它方法可以使用.若使用public关键字,则其它类的方法也可以使用此常量. 字符串: Java中,允许使用+号拼接两个字符串. Java

java之线程飞机大战制作

import java.awt.Graphics; import java.util.ArrayList; import javax.swing.JFrame; import javax.swing.JPanel; public class PlaneMain extends JPanel { public static void main(String[] args) { new PlaneMain(); } private ArrayList<View> list; public Plan

java学习第一个小项目--商品系统

是 对于java学习的前期,大约学了三周左右,我们在老师的带领下写了这个商品系统,功能比较简单,运用的都是java学习前期比较基础的知识 这是我对这个系统的名字与包和class文件的命名. 主要创建的是商品和生产者之间,Commodity和producer. 创建商品的基本属性(成员变量),以及一个无参钩爪方法 重点是Producer类中的编写. 按照序列号对商品进行升序排序 按照商品保质期的长短对商品进行排序 下面是主程序里面,加入自己创建的商品数据,对商品系统进行测试,看是否有一些功能没有实

java学习之坦克大战游戏

总结:由于这几天快过年比较忙然后没怎么写,写代码途中一些经验总结现在给忘记了.这次的小项目感觉比上次写的思路清楚了点.没有之前第一次写那么逻辑混乱,结构也搞的比之前的要好,添加功能比较容易.学习了之前的经验,操作对象的方法由对象本身提供.不过这次小项目还有不足和不完善之处,有些可以做的功能没有实现,比如游戏存档,这里应该可以用下对象的序列化,还有游戏难度的设置也可以写个文件弄出来.要过年了,到处走亲戚没什么心思写了,这里只能留个尾巴了. 前言:之前的及时通信项目完成后感觉线程方面和对java的运

java学习之即时通信项目实战

 项目总结:这次项目主要是根据视频来的,结果跟到一半感觉跟不上,慢慢自己有了自己的想法,决定自己先不看学习视频,自己先试着写. 总结写前面,算是写的第一个项目吧.项目中遇到几点问题,首先Scoket对象创建后,服务器端和客户端不能同时创建输入流,否者会引起堵塞. 然后,读入流应该重新创建个线程做等待写入服务,因为读入流会引起当前线程进入阻塞状态.      还有一个用户线程对应一个服务线程,不是多个用户线程对应一个服务线程.      对对象的操作应该由那个对象本身提供操作方法,比如操作UI界面

Java学习(二)--java概述

一 发展 看了java的发展史,发现他的发展充满了戏剧性.它没有经过精心的策划.制作,但是它的产生却具有了划时代的意义,一切的形成都好像顺利成章,又充满了传奇. 1990年,sun公司准备为下一代只能家电编写通用控制系统.因为C++的api存在的问题,创造了一种新的语言oak. 1992年,在其竞争机顶盒平台倡议中,因其过分给用户控制权而落选.否极泰来,在这里得到了最好的验证,再坚持一点点.下一个一点点就是转机. 1994年,互联网和浏览器的出现给oak带了希望.进过调整后,着眼于浏览器方法.更

Java学习二:Javac Java的学习(原创)

安装完了JDK,就可以编译.执行简答的Java程序了, 一.Javac  ,Java 路径名和包名的关系: 在D盘下,建文件夹Test,在Test里创建文件Java1.java(类名要与文件名一致) Java1.java  : package Test; public  class  Java1 { public static void  main(String[] args) { system.out.println("hello world"); } } 使用的命令: d:\Tes

JAVA学习&lt;二&gt;

1.JAVA中的关键字: Java 关键字是区分大小写的哦!所以 void 是关键字,但 Void 就不是了~~ 2.JAVA标识符: 标识符就是用于给 Java 程序中变量.类.方法等命名的符号. 使用标识符时,需要遵守几条规则: 1.  标识符可以由字母.数字.下划线(_).美元符($)组成,但不能包含 @.%.空格等其它特殊字符,不能以数字开头.譬如:123name 就是不合法滴 2.  标识符不能是 Java 关键字和保留字( Java 预留的关键字,以后的升级版本中有可能作为关键字),