自制一个弹球小游戏(注释详尽,易懂文章)

自制一个弹球小游戏

先来看一下效果:
这是游戏界面:
在这里插入图片描述
这是你歇菜的界面:
在这里插入图片描述

1.基础的思路:

废话不多说,进入正题,首先我们创建一个PinBall类,然后把相关的类导入进来,并在里面创建一个init方法,在创建主类调用该方法:

import javax.swing.*;
import java.awt.*;
import java.awt.event.*;


public class PinBall {


 public void init(){
    }
 
 public static void main(String[] args) {
     new PinBall().init();
    }
}
 

2.创建需要的相关对象和组件:

import javax.swing.*;
import java.awt.*;
import java.awt.event.*;


public class PinBall {

Frame frame =new Frame("弹球游戏");
//桌面宽度和高度
    private final int TABLE_WIDTH=300;
    private final int  TABLE_HEIGHT=400;

    //球拍的高度和宽度
    private final int RACKET_WIDTH=60;
    private final int  RACKET_HEIGHT=20;

    //小球的大小
    private final int BALL_SIZE=16;

    //定义变量,记录小球的坐标
    private int ballX=120;
    private  int ballY=20;

    //定义变量,记录小球在x和y方向分别移动的速度
    private int speedX=2;
    private int speedY=1;

    //定义变量,记录球拍的坐标
    private int racketX=120;
    private final int racketY=340;

    //定义变量,标识当前游戏是否结束
    private boolean isOver=false;

    //声明一个定时器
    private Timer timer;

 //自定义一个类,继承Canvas,充当画布
    private class MyCanvas extends Canvas{
        @Override
        public void paint(Graphics g) {
                //绘制内容
            if(isOver){
                //游戏结束时展示的文字
                g.setColor(Color.BLUE);//颜色
                g.setFont(new Font("Times",Font.BOLD,30));//字体
                g.drawString("游戏结束!",50,200);//坐标
            }
            else  {
                //游戏中
                //绘制小球
                g.setColor(Color.black);
                //绘制一个实体圆形
                g.fillOval(ballX,ballY,BALL_SIZE,BALL_SIZE);

                //绘制球拍,实际就是一个矩形
                g.setColor(Color.magenta);
                g.fillRect(racketX,racketY,RACKET_WIDTH,RACKET_HEIGHT);
            }

        }
    }

    //创建绘画区域
    MyCanvas drawArea=new MyCanvas();



 public void init(){
 
    }
 
 public static void main(String[] args) {
     new PinBall().init();
    }
}

3.组装视图和游戏逻辑的控制,也就是init()方法,在主类调用即可

    public void init(){
     //组装视图,游戏逻辑控制

    //完成球拍坐标的变化,使用键盘监听器
    KeyListener listener =new KeyAdapter() {
        @Override
        public void keyPressed(KeyEvent e) {
            //获取当下按下的键
            int keyCode=e.getKeyCode();

            if(keyCode==KeyEvent.VK_LEFT)
            {//<-应该向左移动,球拍
                if(racketX>0){
                    racketX-=20;
                }
            }
            if(keyCode==KeyEvent.VK_RIGHT)
            {//->应该向右移动,球拍
                if(racketX<(TABLE_WIDTH-RACKET_WIDTH)){
                    racketX+=20;
                }
            }
        }
    };

        //叉叉的监听器
        frame.addWindowListener(new WindowAdapter() {
            @Override
            public void windowClosing(WindowEvent e) {
                System.exit(0);
            }
        });

    //给Frame和drawArea注册监听器
    frame.addKeyListener(listener);
    drawArea.addKeyListener(listener);

    //小球坐标的控制
    ActionListener task=new ActionListener() {
        @Override
        public void actionPerformed(ActionEvent e) {
           //根据边界范围修正速度
               if(ballX<=0||ballX>=(TABLE_WIDTH-BALL_SIZE)){
                speedX=-speedX ;}

               if(ballY<=0||(ballY>racketY-BALL_SIZE&&ballX>racketX&&ballX<racketX+RACKET_WIDTH))
               {speedY=-speedY;}
               if(ballY>racketY-BALL_SIZE&&(ballX<racketX||ballX>racketX+RACKET_WIDTH)){
             //当前小球超出球拍范围,游戏结束
                   //停止定时器
                   timer.stop();
                   //修改游戏是否结束标记
                   isOver=true;
                   //重绘界面
                   drawArea.repaint();
               }

            //更新小球的坐标,重绘界面
            ballX+=speedX;
            ballY+=speedY;
             //重绘界面
            drawArea.repaint();
        }
    };
    //间隔10毫秒,来重绘
 timer=new Timer(10,task);
 timer.start();

 //设置画布大小,就是桌面的大小
 drawArea.setPreferredSize(new Dimension(TABLE_WIDTH,TABLE_HEIGHT));
 frame.add(drawArea);

 //设置frame最佳大小并可视
frame.pack();
frame.setVisible(true);
}

完整代码:

import javax.swing.*;
import java.awt.*;
import java.awt.event.*;


public class PinBall {
Frame frame =new Frame("弹球游戏");
//桌面宽度和高度
    private final int TABLE_WIDTH=300;
    private final int  TABLE_HEIGHT=400;

    //球拍的高度和宽度
    private final int RACKET_WIDTH=60;
    private final int  RACKET_HEIGHT=20;

    //小球的大小
    private final int BALL_SIZE=16;

    //定义变量,记录小球的坐标
    private int ballX=120;
    private  int ballY=20;

    //定义变量,记录小球在x和y方向分别移动的速度
    private int speedX=2;
    private int speedY=1;

    //定义变量,记录球拍的坐标
    private int racketX=120;
    private final int racketY=340;

    //定义变量,标识当前游戏是否结束
    private boolean isOver=false;

    //声明一个定时器
    private Timer timer;

    //自定义一个类,继承Canvas,充当画布
    private class MyCanvas extends Canvas{
        @Override
        public void paint(Graphics g) {
                //绘制内容
            if(isOver){
                //游戏结束时展示的文字
                g.setColor(Color.BLUE);//颜色
                g.setFont(new Font("Times",Font.BOLD,30));//字体
                g.drawString("游戏结束!",50,200);//坐标
            }
            else  {
                //游戏中
                //绘制小球
                g.setColor(Color.black);
                //绘制一个实体圆形
                g.fillOval(ballX,ballY,BALL_SIZE,BALL_SIZE);

                //绘制球拍,实际就是一个矩形
                g.setColor(Color.magenta);
                g.fillRect(racketX,racketY,RACKET_WIDTH,RACKET_HEIGHT);
            }

        }
    }

    //创建绘画区域
    MyCanvas drawArea=new MyCanvas();

    public void init(){
     //组装视图,游戏逻辑控制

    //完成球拍坐标的变化,使用键盘监听器
    KeyListener listener =new KeyAdapter() {
        @Override
        public void keyPressed(KeyEvent e) {
            //获取当下按下的键
            int keyCode=e.getKeyCode();

            if(keyCode==KeyEvent.VK_LEFT)
            {//<-应该向左移动,球拍
                if(racketX>0){
                    racketX-=20;
                }
            }
            if(keyCode==KeyEvent.VK_RIGHT)
            {//->应该向右移动,球拍
                if(racketX<(TABLE_WIDTH-RACKET_WIDTH)){
                    racketX+=20;
                }
            }
        }
    };

        //叉叉的监听器
        frame.addWindowListener(new WindowAdapter() {
            @Override
            public void windowClosing(WindowEvent e) {
                System.exit(0);
            }
        });

    //给Frame和drawArea注册监听器
    frame.addKeyListener(listener);
    drawArea.addKeyListener(listener);

    //小球坐标的控制
    ActionListener task=new ActionListener() {
        @Override
        public void actionPerformed(ActionEvent e) {
           //根据边界范围修正速度
               if(ballX<=0||ballX>=(TABLE_WIDTH-BALL_SIZE)){
                speedX=-speedX ;}

               if(ballY<=0||(ballY>racketY-BALL_SIZE&&ballX>racketX&&ballX<racketX+RACKET_WIDTH))
               {speedY=-speedY;}
               if(ballY>racketY-BALL_SIZE&&(ballX<racketX||ballX>racketX+RACKET_WIDTH)){
             //当前小球超出球拍范围,游戏结束
                   //停止定时器
                   timer.stop();
                   //修改游戏是否结束标记
                   isOver=true;
                   //重绘界面
                   drawArea.repaint();
               }

            //更新小球的坐标,重绘界面
            ballX+=speedX;
            ballY+=speedY;
             //重绘界面
            drawArea.repaint();
        }
    };
    //间隔10毫秒,来重绘
 timer=new Timer(10,task);
 timer.start();

 //设置画布大小,就是桌面的大小
 drawArea.setPreferredSize(new Dimension(TABLE_WIDTH,TABLE_HEIGHT));
 frame.add(drawArea);

 //设置frame最佳大小并可视
frame.pack();
frame.setVisible(true);
}
    public static void main(String[] args) {
     new PinBall().init();
    }
}

总结:通过这个我学习到了很多,关于监听器和定时器如何使用,明白在重绘时paint方法是AWT系统负责调用。了解到了,动画效果是在不断绘制变化的图像,因为使用定时器的原因,重绘时间短,导致肉眼无法分辨出。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

yjg_

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值