用JAVA实现雷电小游戏

用JAVA实现雷电小游戏

  1. 效果图如下:
    雷电
  2. 实现雷电小游戏,主要创建了三个类:Ball类、BallJPanel类、BallJFrame类

    Ball类中定义了敌方战机、子弹和我方子弹,将该三者都看成圆,即看成同一个类
    Ball类中包含dr()<画出敌机及其子弹>、mv()<敌机及其子弹的移动>、isTouch()<判断子弹之间是否碰撞>方法

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    22
    23
    24
    25
    26
    27
    28
    29
    30
    31
    32
    33
    34
    35
    36
    37
    38
    39
    40
    41
    42
    43
    44
    45
    46
    47
    48
    49
    50
    51
    52
    53
    54
    55
    56
    57
    public class Ball {
    int x,y;//圆角坐标
    int r;
    int ori;//方向 4向上 5向下
    int type;//标记类型,0我方发出,1敌方发出
    //awt包中Swing界面能识别图片的类
    public static Image image_fire =
    new ImageIcon("fire.gif").getImage();
    public static Image image_el =
    new ImageIcon("el_0.gif").getImage();
    //构造器
    public Ball(){

    }
    public Ball(int x, int y, int r, int ori, int type){
    this.x = x;
    this.y = y;
    this.r = r;
    this.ori = ori;
    this.type = type;
    }
    //画在相应的JPanel中
    public void dr(Graphics g){
    switch (type){
    case 0:
    g.drawImage(image_fire,x,y,
    2*r,2*r,null);
    break;
    case 1:
    g.drawImage(image_el,x,y,
    2*r,2*r,null);
    break;
    }
    }
    //判断两个球是否相遇
    public boolean isTouch(Ball ball2){
    boolean isTouch = false;
    //第一个圆心坐标
    int x1 = x + r;
    int y1 = y + r;
    //b2圆心坐标
    int x2 = ball2.x + ball2.r;
    int y2 = ball2.y + ball2.r;
    double s = Math.sqrt((x2-x1)*(x2-x1)+(y2-y1)*(y2-y1));
    if (s<=r+ball2.r){
    isTouch = true;
    }
    return isTouch;
    }
    //我方子弹或敌机及其子弹移动
    public void mv(){
    switch (ori){
    case 4: y--;break;
    case 5: y++;break;
    }
    }
    }

    BallJPanel类中定义了画笔类、鼠标事件、监听器、多线程、我方飞机类等

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    22
    23
    24
    25
    26
    27
    28
    29
    30
    31
    32
    33
    34
    35
    36
    37
    38
    39
    40
    41
    42
    43
    44
    45
    46
    47
    48
    49
    50
    51
    52
    53
    54
    55
    56
    57
    58
    59
    60
    61
    62
    63
    64
    65
    66
    67
    68
    69
    70
    71
    72
    73
    74
    75
    76
    77
    78
    79
    80
    81
    82
    83
    84
    85
    86
    87
    88
    89
    90
    91
    92
    93
    94
    95
    96
    97
    98
    99
    100
    101
    102
    103
    104
    105
    106
    107
    108
    109
    110
    111
    112
    113
    114
    115
    116
    117
    118
    119
    120
    121
    122
    123
    124
    125
    126
    127
    128
    129
    130
    131
    132
    133
    134
    135
    136
    137
    138
    139
    140
    141
    142
    143
    144
    145
    146
    147
    148
    149
    150
    151
    152
    153
    154
    155
    156
    157
    158
    159
    160
    161
    162
    163
    164
    165
    166
    167
    168
    169
    170
    171
    172
    173
    174
    175
    176
    177
    178
    179
    180
    181
    182
    183
    184
    185
    186
    187
    188
    189
    190
    191
    192
    193
    194
    195
    196
    197
    /**
    * @author threee
    * @date 2020/2/14 - 13:20
    * 单继承 多实现
    * MouseMotionListener拖动,移动事件
    * MouseListener鼠标点击事件
    */
    public class BallJPanel extends JPanel
    implements MouseListener, MouseMotionListener,Runnable {
    //我方子弹集合
    ArrayList<Ball> allBalls;
    //敌方子弹飞机集合
    ArrayList<Ball> allSnows;
    //是否开火,true开火
    boolean isFire;
    //积分
    int score;
    //我方飞机图片
    Image hero_img = new ImageIcon("hero.gif").getImage();
    //监听:随时准备好,等待事件的触发,一旦触发,相应的方法会发生效果
    //监听代码放在构造器中,表示BallJPanel一初始化就可监听了
    public BallJPanel(){
    //第一个this代表当前BallJPanel
    //第二个this代表当前鼠标事件
    this.addMouseListener(this);
    this.addMouseMotionListener(this);
    //我方飞机默认出现的位置
    plane.x = 100;
    plane.y = 400;
    //得分默认为0
    score = 0;
    allBalls = new ArrayList<>();
    allSnows = new ArrayList<>();
    }

    @Override
    public void paint(Graphics g) {
    super.paint(g);
    //显示背景图
    //通过当前类所有的目录取路径
    URL imgURL = getClass().getResource("back.jpg");
    ImageIcon icon = new ImageIcon(imgURL);
    //放入图片
    g.drawImage(icon.getImage(),0,0,400,600,this);
    //我方飞机
    g.drawImage(hero_img,plane.x,plane.y,200,100,null);
    //积分
    g.setColor(Color.red);
    g.setFont(new Font("宋体",Font.BOLD,24));
    g.drawString("积分",300,35);
    g.drawString(String.valueOf(score),350,35);
    g.drawString("生命",300,60);
    g.drawString(String.valueOf(plane.life),350,60);
    //假设allBalls有Ball时,每个ball要画出来
    for (int i=0;i<allBalls.size(); i++){
    Ball b = allBalls.get(i);
    b.dr(g);
    }
    for (int i=0;i<allSnows.size(); i++){
    Ball b = allSnows.get(i);
    b.dr(g);
    }
    }
    //线程需要做的事
    @Override
    public void run() {
    //判断isFire是否为true
    int count = 0;
    while(true){
    //通过count控制频率
    count++;
    if (count>=Integer.MAX_VALUE){
    count = 0;
    }
    //不断落下的敌机
    if(count%60 == 0){
    Ball b = new Ball((int)(Math.random()*400),
    -50,30,5,1);
    allSnows.add(b);
    }
    //敌方飞机子弹下移
    for (int i=0; i<allSnows.size(); i++){
    Ball b1 = allSnows.get(i);
    b1.mv();
    if (b1.y>600){
    allSnows.remove(b1);
    }
    }
    //判断isFire是否为true
    if (isFire && count%100 == 0){
    Ball ball1 = new Ball(plane.x+100,plane.y+50,20,4,0);
    allBalls.add(ball1);
    }
    //我方子弹上移
    for (int i=0; i<allBalls.size(); i++){
    Ball b2 = allBalls.get(i);
    b2.mv();
    if (b2.y<0){
    allBalls.remove(b2);
    }
    }
    //当我方子弹遇到敌机时,双方都消失,积分 +10
    for (int i=0; i<allBalls.size(); i++){
    for (int j=0; j<allSnows.size(); j++){
    if ( i<allBalls.size() && j<allSnows.size()
    && allBalls.get(i).isTouch(allSnows.get(j))){
    allBalls.remove(i);
    allSnows.remove(j);
    score += 10;
    }
    }
    }
    //我方战机碰撞敌方战机时,生命 -10
    for (int i=0; i<allSnows.size(); i++){
    if (i<allSnows.size() && plane.isCrash(allSnows.get(i))){
    plane.life -= 10;
    allSnows.remove(i);
    if(plane.life <= 0){
    plane.die = true;
    //弹出信息提示框
    JOptionPane.showMessageDialog(null,"GAME OVER!");
    }
    }
    }
    if (plane.die){
    System.exit(0);
    }
    try {
    Thread.sleep(20);
    } catch (InterruptedException e) {
    e.printStackTrace();
    }
    repaint();
    }
    }
    @Override
    public void mouseClicked(MouseEvent e) {

    }

    @Override
    public void mousePressed(MouseEvent e) {
    isFire = true;
    }

    @Override
    public void mouseReleased(MouseEvent e) {
    isFire = false;
    }

    @Override
    public void mouseEntered(MouseEvent e) {

    }

    @Override
    public void mouseExited(MouseEvent e) {

    }

    @Override
    //拖动
    public void mouseDragged(MouseEvent e) {
    //e是鼠标的实时位置
    plane.x = e.getX()-100;
    plane.y = e.getY()-50;
    repaint();
    }

    @Override
    public void mouseMoved(MouseEvent e) {
    //e是鼠标的实时位置
    // x = e.getX();
    // y = e.getY();
    // repaint();
    }
    }
    class plane{
    //我方飞机坐标
    static int x,y;
    //我方飞机生命值
    static int life = 100;
    //飞机是否死亡
    static boolean die = false;
    public static boolean isCrash(Ball ball2){
    boolean isCrash = false;
    int x1 = plane.x + 100;
    int y1 = plane.y + 50;
    int x2 = ball2.x + ball2.r;
    int y2 = ball2.y + ball2.r;
    double s = Math.sqrt((x2-x1)*(x2-x1)+(y2-y1)*(y2-y1));
    if (s<=30+ball2.r){
    isCrash = true;
    }
    return isCrash;
    }
    }

    BallJFrame类中定义了主窗体,main方法。用sh()方法画出界面,构造器运行线程

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    public class BallJFrame extends JFrame {
    BallJPanel jPanel;
    public BallJFrame(){
    jPanel = new BallJPanel();
    this.add(jPanel);
    Thread thread = new Thread(jPanel);
    thread.start();
    }
    //写一个方法画出界面
    public void sh(){
    this.setSize(400,600);
    this.setTitle("雷电");
    //当点击JFrame关闭时,整个程序也随之关闭
    this.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
    this.setVisible(true);
    }
    public static void main(String[] args) {
    BallJFrame jFrame = new BallJFrame();
    jFrame.sh();
    }
    }
  3. 本次实践知识总结
    1. 把图片放入窗体中有两种方法:
      (1)、通过URL查找当前类的目录路径,再赋给ImageIcon类的对象,再用画笔类drawImage方法画出 (图片放在当前类的同一个包下)
    1
    2
    3
    4
    5
    //通过当前类所有的目录取路径
    URL imgURL = getClass().getResource("back.jpg");
    ImageIcon icon = new ImageIcon(imgURL);
    //放入图片
    g.drawImage(icon.getImage(),0,0,400,600,this);
    (2)、直接new一个ImageIcon类的对象赋给Image类的对象,再用画笔类drawImage方法画出(图片放在项目的根目录下)
    1
    2
    3
    4
    5
    6
    7
    8
    9
    //awt包中Swing界面能识别图片的类
    public static Image image_fire =
    new ImageIcon("fire.gif").getImage();
    public static Image image_el =
    new ImageIcon("el_0.gif").getImage();
    g.drawImage(image_fire,x,y,
    2*r,2*r,null);
    g.drawImage(image_el,x,y,
    2*r,2*r,null);
    1. java中添加信息弹出框的方法:
    1
    JOptionPane.showMessageDialog(null,"GAME OVER!");
文章作者: 刘山
文章链接: http://threee-hub.github.io/2020/02/14/java%E5%AE%9E%E7%8E%B0%E9%9B%B7%E7%94%B5%E5%B0%8F%E6%B8%B8%E6%88%8F/
版权声明: 本博客所有文章除特别声明外,均采用 CC BY-NC-SA 4.0 许可协议。转载请注明来自 刘山的博客