java graphical gadget Abstract Window Toolit: brush Graphics, canvas Canvas(), pinball game

BrushGraphics

Java provides the Graphics class, which is an abstract brush that can draw colorful geometric figures and bitmaps on the Canvas component (canvas).

The commonly used drawing methods in Graphics are as follows:

  • drawLine(): draw a straight line
  • drawString(): draw a string
  • drawRect(): Draw a rectangle
  • drawRoundRect(): Draw a rectangle with rounded corners
  • drawOval(): Draw an ellipse
  • drawPolygon(): Draw polygon border
  • drawArc(): Draw an arc (possibly an arc of an ellipse)
  • drawPolyline(): draw polyline
  • fillRect(): fill a rectangular area
  • fillRoundRect(): Fill a rounded rectangular area
  • fillOval(): fill oval
  • fillPolygon(): fill polygon border
  • fillArc(): Fill an arc (maybe an arc of an ellipse)
  • drawImage(): Draw bitmap

AWT specifically provides a Canvas class as the canvas for drawing . The program can realize drawing by creating a subclass of Canvas and overriding its paint() method.

Test code:

  • Canvas() canvas class paint method draws pictures, and the brush parameter is passed in the method
  • Canvas() canvas class setSize(250,250); method sets the canvas size
  • Canvas()Canvas class repaint(); //Redraw after clearing
  • The Graphics().setColor method sets the brush color, and the brush performs drawing actions (red value, green value, blue value). The value range of red, green and blue colors is 0-255, which can be combined to form any color visible to humans.
 
 
import java.awt.*;
import java.awt.event.*;
import java.util.Random;
import java.util.concurrent.atomic.AtomicReference;
 
/**
 * @ClassName DrawSimple
 * @projectName: object1
 * @author: Zhangmingda
 * @description: XXX
 * date: 2021/5/7.
 */
public class DrawSimple {
    public static void main(String[] args) {
        //窗口
        Frame frame = new Frame("简单画图示例");
 
        //窗口关闭按钮动作
        WindowListener closeListener = new WindowAdapter() {
            @Override
            public void windowClosing(WindowEvent e) {
                System.out.println("窗口关闭");
                System.exit(0);
            }
        };
        frame.addWindowListener(closeListener);
        //绘制图形形状变量
        AtomicReference<String> shape = new AtomicReference<>();
        //画布
        Canvas canvas = new Canvas(){
            Random random = new Random();
            @Override
            public void paint(Graphics g) { //g为画笔
                System.out.println("画图中");
                if (shape.get() != null){
                    switch (shape.get()){
                        case "rect":
                            //设置画笔颜色Color(红色值,绿色值,蓝色值) 红绿蓝三色取值范围0-255 组合起来可以组成人类可见的任何颜色
                            g.setColor(new Color(255,0,0));
                            //画矩形,x,y分别为起始位置,后面两个参数为宽,高 Random.nextInt(200) 为伪随机数
                            g.drawRect(20,20,random.nextInt(200),random.nextInt(200));
                            break;
                        case "oval":
                            //画椭圆
                            g.setColor(new Color(10,100,30));
                            g.drawOval(40,20,random.nextInt(200),random.nextInt(200));
                    }
                }
            }
        };
        canvas.setSize(250,250);
        frame.add(canvas);
 
        //容器
        Panel panel = new Panel();
        //按钮
        Button drawRectBtn = new Button("画矩形");
        Button drawOvalBtn = new Button("画椭圆");
        //按钮绑定事件
        drawRectBtn.addActionListener(e ->{
            shape.set("rect");
            canvas.repaint(); //清除后重新绘制
        });
        drawOvalBtn.addActionListener(e ->{
            shape.set("oval");
            canvas.repaint(); //清除后重新绘制
        });
        panel.add(drawOvalBtn);
        panel.add(drawRectBtn);
        frame.add(panel,BorderLayout.SOUTH);
        //窗口自动调整大小
        frame.setLocation(400,300);
        frame.pack();
        frame.setVisible(true);
    }
}

Develop a pinball game

Development idea: Animation is to redraw a new image at a certain interval (usually less than 1 second). The difference between the two drawn images is small, and it looks like a so-called animation to the naked eye. For this program we need to use a Timer class from the Swing package.

Timer(int delay, ActionListener listener): Every delay seconds, the system automatically triggers the event handler (actionPerformed method) in the ActionListener listener.

Knowledge points:

  • KeyListener implements monitoring keyboard keys to trigger moving racket
  • Drawing logic: When the ball reaches the left and right ends of the X-axis of the canvas, it moves in the opposite direction, when it reaches the top position of the Y-axis 0, or when it reaches the racket contact area, it moves in the opposite direction.
  • Timer timer, redraw the picture every millisecond level
  • All variables used are defined as class variables

 Sample code:

import com.sun.source.tree.NewClassTree;
 
import javax.swing.*;
import java.awt.*;
import java.awt.event.*;
import java.util.Random;
 
/**
 * @ClassName Pinball
 * @projectName: object1
 * @author: Zhangmingda
 * @description: XXX
 * date: 2021/5/7.
 */
public class Pinball {
    //定义球拍初始位置用随机对象
    private Random random = new Random();
    /**
     * 设置画布大小:宽高
     */
    private int canvaWidth = 300;
    private int canvaHeight = 400;
    /**
     * 球拍初始参数
     */
    //拍子大小位置
    private int rectX = random.nextInt(200); //拍子所在横坐标位置,要在画布范围之内,
    private int rectY = 355; //拍子所在Y轴坐标位置小于400,和底部留一定空隙
    private int rectWidth = 60; //宽度60
    private int rectHeight = 15; //厚度
    //拍子按下按键拍子移动的像素大小(步伐)
    int pace =10;
 
    /**
     * 小球的尺寸位置初始参数
     */
    private int ballSize =15;
    private int ballX = random.nextInt(200);
    private int ballY = random.nextInt(100);
 
    /**
     * 小球运动速度值
     */
    private int ballYSpeed = 5; //Y 轴移动速度
    private double xyRate = random.nextDouble() - 0.5; //X轴相对比Y轴运动速度的比率,返回一个-0.5 ~0.5之间的数,移动方向为向左或者向右
    private int ballXSpeed = (int) (ballYSpeed * xyRate * 2); // X 轴运动的速度
 
    /**
     * 定时器Timer
     */
    private Timer timer;
 
    /**
     * 游戏是否结束
     */
    private boolean gameOver = false;
 
    /**
     * 方法
     */
    public void play(){
        /**
         * 定义窗口,设置位置和关闭动作
         */
        Frame frame = new Frame("弹球小游戏");
        frame.setLocation(400,300);
        frame.addWindowListener(new WindowAdapter() {
            @Override
            public void windowClosing(WindowEvent e) {
                System.out.println("关闭游戏");
                System.exit(0);
            }
        });
 
        /**
         * 定义画布
         */
        Canvas canvas = new Canvas(){
            @Override
            public void paint(Graphics g) {
                //如果没有结束
                if (!gameOver){
                    //画球
                    g.setColor(new Color(30,200,150));
                    g.fillOval(ballX,ballY,ballSize, ballSize);
                    //画下面的矩形拍子
                    g.setColor(new Color(75, 79, 194));
                    g.fillRect(rectX, rectY, rectWidth, rectHeight);
                }else { //gameOver了
                    g.setColor(Color.RED);
                    g.setFont(new Font("Times",Font.BOLD,30)); // 设置字体格式字体
                    g.drawString("Game Over",70, 200);
                }
            }
        };
        //设置画布大小
        canvas.setPreferredSize(new Dimension(canvaWidth,canvaHeight));
        frame.add(canvas);
        /**
         * 游戏核心逻辑:动画效果
         */
        timer = new Timer(50, new ActionListener() {
            @Override
            public void actionPerformed(ActionEvent actionEvent) {
                /**
                 * 如果到了X轴的两端,就向反方向画图
                 */
                if (ballX < 0 || ballX >= canvaWidth - ballSize)
                    ballXSpeed = -ballXSpeed;
                /**
                 * 如果球接触到了球拍的X轴和Y轴区域内,或者跑到顶端(ballY 坐标小于0)就把Y轴反向移动
                 */
                if (ballY < 0 || (ballY >= rectY - ballSize && ballY  < rectY - ballSize/2) && ballX + ballSize /2 >= rectX && ballX + ballSize /2 <= rectX + rectWidth) {
                    System.out.println("ballX:"+ ballX + "ballY:"+ ballY + "rectX:" + rectX + "rectY:" +rectY);
                    ballYSpeed = -ballYSpeed; //反向速度
                }else if (ballY >= canvaHeight){ //如果球已经掉到画布之外或者 球拍下 就停止timer循环
                    timer.stop();
                    gameOver = true;
                }
                ballX += ballXSpeed;
                ballY += ballYSpeed;
                canvas.repaint();
            }
        });
        timer.start();
        /**
         * 窗口监听键盘
         */
        KeyListener keyListener = new KeyAdapter() { //添加键盘监听器
            @Override
            public void keyPressed(KeyEvent e) { //当键盘被按下时触发
//                System.out.println("按下键盘");
                int KeyCode = e.getKeyCode(); //获取按下的键盘代号
                switch (KeyCode){
                    case KeyEvent.VK_LEFT://左键按下
                        if(rectX - pace > 0){
                            rectX -= pace;
                        }else {
                            rectX = 0;
                        }
                        break;
                    case KeyEvent.VK_RIGHT://右键按下
                        if (rectX + pace < canvaWidth - rectWidth){
                            rectX += pace;
                        }else {
                            rectX = canvaWidth -rectWidth;
                        }
                        break;
                }
                canvas.repaint();
            }
        };
        frame.addKeyListener(keyListener);
        /**
         * 窗口大小自动调节到最优,显示窗口
         */
        frame.pack();
        frame.setVisible(true);
    }
    public static void main(String[] args) {
        new Pinball().play();
    }
}

Guess you like

Origin blog.csdn.net/lmrylll/article/details/130440482