当前位置: 代码迷 >> 综合 >> JAVA学习笔记第九、十、十一天——JFrame、JPanel实现项目实践飞机大战
  详细解决方案

JAVA学习笔记第九、十、十一天——JFrame、JPanel实现项目实践飞机大战

热度:37   发布时间:2024-02-01 11:02:27.0

回顾–面向对象小结:

继承: 类 和 类, 单继承 extends

子类继承父类:1.继承父类中所有可见的成员方法和成员变量2.父类的构造方法不能被子类继承, 只能被子类调用3.子类可以重写父类的方法方法名和参数列表一样返回值类型, 小于等于 父类的返回值类型权限, 大于等于 父类的权限
子类调用父类:super() -> 调用父类无参构造方法super.m1() -> 调用父类的成员方法super.a -> 调用父类的成员变量super 只能在子类中使用this: 当前对象, 自己static: 属于类, 通过 类名. 来调用static{} -> 静态代码块, 类加载时执行

类加载:

1.创建类的对象
2.调用类的静态成员
3.创建子类对象, 先加载父类, 再加载子类
4.调用子类的静态成员, 先加载父类, 再加载子类
5.Class.forName(String className): 手动加载java.lang.String  java.util.ArrayList

抽象abstract:

抽象方法: 只能存在于抽象类或者接口中
抽象类: 可以用来放抽象方法不能实例化有构造方法, 给自类调用的

final:

final class -> 不能被继承
final void m1() -> 不能被重写
final int a -> 不能被改变, 常量, 必须初始化成员变量a, 必须在创建对象时初始化
final static int B -> 必须初始化, 静态常量类加载时, 必须初始化完成
常量: 固定几个选项时, 通常类型都是int将选项起个名字-变量, final 变量如果常量要在外部无关类中使用, 通常为了方便, 都会定义成static

实现: 接口

抽象方法 -> 必须被实现类重写/覆盖的
静态常量 -> 直接通过接口类型使用
默认方法 -> 有具体实现, 可以不被重写
静态方法 -> 直接通过接口类型使用
私有方法 -> 给默认方法提供的使用接口, 必须有实现类, 并且创建实现类对象

多态: 编译时看左边, 运行时看右边

父类 a = new 子类();
接口 b = new 接口实现类();
a.m1(): 说明m1声明在父类中子类重写了m1方法
编译时类型: 只在编译时有效泛型
a 想要调用子类特有的方法, 需要强制转换可能会出现 ClassCastException解决方式, 提前使用 a instanceof 子类
意义: 扩展方法的功能

内部类:

成员内部类 -> 类中

    public class Outer{public class Inner{}}Outer.Inner in = new Outer().new Inner()

局部内部类 -> 方法中

    public void m1() {int a = 10;class Inner {// 使用a, a必须是final}}只在方法中可以使用, 一次性

匿名内部类

    接口/抽象类 b = new 接口/抽象类() {// 真正的类, 重写抽象方法}只能创建一次对象

静态内部类 -> 属于类的

    public class Outer{public static class Inner{}}Outer.Inner in = new Outer.Inner()

权限:

外部类: public/(default)
成员内部类: public/protected/(default)/private
局部内部类: 不能使用
方法: public/protected/(default)/private
成员变量: public/protected/(default)/private
局部变量: 不能使用

Java swing: 窗口化界面

软件包:
java.awt
javax.swing
1.窗口显示 JFrame
2.画板/面板 JPanel
原生的 JPanel 中, 不能自定义绘画
只能画 按钮, 输入框.. 等一些组件
功能加强 -> 自定义类继承 JPanel
3.图片读取1.硬盘中有图片文件2.将硬盘中的图片文件, 读取到JVM内存中, 成一个对象InputOutput -> IO

JFrameDemo

import javax.swing.*;
import java.util.Arrays;
import java.util.Scanner;
//import java.util.*;public class JFrameDemo {public static void main(String[] args) {
// Arrays.toString(new int[]{});
// Scanner console = new Scanner(System.in);// 空参构造方法 -> 创建一个原始的很小的窗口JFrame window = new JFrame();window.setTitle("飞机大战");// 有参构造方法 -> 参数:窗口标题
// JFrame window = new JFrame("飞机大战");// 设置窗口大小window.setSize(400, 650);// 设置窗口的默认关闭选项 0~3window.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);// 设置窗口居中window.setLocationRelativeTo(null);// 设置置顶window.setAlwaysOnTop(true);// 设置窗口没有外边框window.setUndecorated(true);// 显示窗口window.setVisible(true);}
}

JPanelDemo

import javax.swing.*;
import java.awt.*;
import java.awt.image.BufferedImage;public class JPanelDemo {public static void main(String[] args) {JFrame window = new JFrame();// 3.创建子类对象MyPanel p = new MyPanel();// 4.将画板对象添加到窗口对象中window.add(p);window.setSize(400, 600);window.setVisible(true);}
}
// 1.自定义类, 来继承JPanel
class MyPanel extends JPanel {// 2.重写自定义绘画方法@Overridepublic void paint(Graphics g) {super.paint(g);// 以下是绘画的自定义增强// 设置 g -> 画笔 的字体属性Font font = new Font("Microsoft YaHei", Font.BOLD, 20);g.setFont(font);// 设置 画笔 颜色/*Color c = new Color(255, 0, 0);g.setColor(c);*/// 英文可译的颜色, 在Color中直接定义好了静态常量g.setColor(Color.BLACK);g.drawString("HelloWorld", 20, 50);paintAirplane(g);}// 将绘画方法拆解 - 便于维护private void paintAirplane(Graphics g) {BufferedImage img = null;// 按照图片原来大小显示g.drawImage(img, 100, 200, this);// 按照规定宽高来显示图片, 缩放g.drawImage(img, 100, 200, 50, 50, this);}}

JPanelDemoImage

import javax.imageio.ImageIO;
import javax.swing.*;
import java.awt.*;
import java.awt.image.BufferedImage;
import java.io.IOException;public class JPanelDemoImage {public static void main(String[] args) {JFrame window = new JFrame();// 3.创建子类对象MyPanel10 p = new MyPanel10();// 4.将画板对象添加到窗口对象中window.add(p);window.setSize(400, 600);window.setVisible(true);}
}// 1.自定义类, 来继承JPanel
class MyPanel10 extends JPanel {// 2.重写自定义绘画方法@Overridepublic void paint(Graphics g) {super.paint(g);// 以下是绘画的自定义增强paintAirplane(g);}// 将绘画方法拆解 - 便于维护private void paintAirplane(Graphics g) {// background.png 和 MyPanel10 同包/同文件夹BufferedImage img = null;try {img = ImageIO.read(MyPanel10.class.getResourceAsStream("background.png"));// 继续读取其他图片} catch (IOException e) {e.printStackTrace();}// 按照图片原来大小显示g.drawImage(img, 0, 0, this);}}

飞机大战

游戏可以产生小的敌机\大的敌机\小蜜蜂 -> 随机,概率
游戏打开, 鼠标单击, 游戏开始, 自动发射子弹, 英雄机跟随鼠标移动
鼠标移动到窗口外面, 游戏暂停, 鼠标移动回来, 游戏继续
子弹打击到敌机和小蜜蜂, 生命值0, 消失
敌机 撞击到英雄机, 英雄机生命值-1, 直到0时, 游戏结束
小敌机: 分数+
大敌机: 分数+ 奖励(生命值加成, 火力加成)
小蜜蜂: 奖励(生命值加成, 火力加成)

4.程序的设计
类的设计
飞机大战:
提取对象: 自己的飞机, 敌机, 小蜜蜂, 子弹
子类 extends 父类
自己的飞机: Hero
发射的子弹, int life, int 分数
敌机: Airplane
小蜜蜂: Bee
子弹: Bullet - 有参的构造方法
大敌机: BigPlane
int 血量
以上类中相同的成员变量, 和相同的方法, 提取出来
父类: FlyingObject
int x, int y, 图片, int width, int height
move() - 移动

读取图片: 程序最开始就一次性读取完
static{}
5.补充类的构造方法
6.在主程序中创建各种对象 测试
7.完成move方法
8.主程序中: 添加定时器
a.生成新的飞行物(小蜜蜂, 敌机, 大敌机)
b.移动所有飞行物
d.发射子弹 - 属于英雄机的行为 - 写在Hero类中
e.移动所有子弹
c.判断飞行物和子弹越界
f.判断子弹和飞行物碰撞
g.英雄机移动 - move - 鼠标控制
h.英雄机和敌机碰撞
i.判断游戏是否结束
z.重画
9.添加鼠标监听事件 - 监听器 - 接口
单击\移动\鼠标移出界面\鼠标移入界面
窗口/画板.addMouseListener -> 单击\鼠标移入\鼠标移出
窗口/画板.addMouseMotionListener -> 鼠标移动
注意:
接口功能太多, 选择性使用功能, 提供了一个适配器 - 抽象类
MouseAdapter - 抽象类, 将所有接口方法空实现
10.游戏状态
a.初始状态 start
b.运行状态 running
c.暂停状态 pause
d.游戏结束 gameover
start -> 鼠标单击 -> running
running -> 移出 -> pause
-> hero.getLife()==0 -> gameover
pause -> 鼠标移入 -> running
gameover -> 鼠标单击 -> start

11.奖励类型: [火力加成], 生命值加成
奖励在对象创建时就已经初始化好
12.碰撞
子弹和飞行物的碰撞: 要么加分, 要么奖励
飞行物和英雄机的碰撞: 减英雄机生命值
13.判断游戏是否结束

分析

在这里插入图片描述

游戏状态

在这里插入图片描述
完整代码链接: 飞机大战.

  相关解决方案