当前位置: 首页 > news >正文

绘图(一)弹球小游戏

AWT编程 · 语雀

仓库:Java图形化界面: Java图形化界面学习demo与资料 (gitee.com)

很多程序如各种小游戏都需要在窗口中绘制各种图形,除此之外,即使在开发JavaEE项目时, 有 时候也必须"动态"地向客户 端生成各种图形、图表,比如 图形验证码、统计图等,这都需要利用AWT的绘图功能。

组件绘图原理

之前我们已经学习过很多组件,例如Button、Frame、Checkbox等等,不同的组件,展示出来的图形都不一样,其实这些组件展示出来的图形,其本质就是用AWT的绘图来完成的。

在AWT中,真正提供绘图功能的是Graphics对象,那么Component组件和Graphics对象存在什么关系,才能让Component绘制自身图形呢?在Component类中,提供了下列三个方法来完成组件图形的绘制与刷新:

paint(Graphics g):绘制组件的外观;

update(Graphics g):内部调用paint方法,刷新组件外观;

repaint():调用update方法,刷新组件外观;

一般情况下,update和paint方法是由AWT系统负责调用,如果程序要希望系统重新绘制组件,可以调用repaint方法完成。

Graphics类的使用

实际生活中如果需要画图,首先我们得准备一张纸,然后在拿一支画笔,配和一些颜色,就可以在纸上画出来各种各样的图形,例如圆圈、矩形等等。

程序中绘图也一样,也需要画布,画笔,颜料等等。AWT中提供了Canvas类充当画布,提供了Graphics类来充当画笔,通过调用Graphics对象的setColor()方法可以给画笔设置颜色。

画图的步骤:

1.自定义类,继承Canvas类,重写paint(Graphics g)方法完成画图;

2.在paint方法内部,真正开始画图之前调用Graphics对象的setColor()、setFont()等方法设置画笔的颜色、字体等属性;

3.调用Graphics画笔的drawXxx()方法开始画图。

其实画图的核心就在于使用Graphics画笔在Canvas画布上画出什么颜色、什么样式的图形,所以核心在画笔上,下表中列出了Graphics类中常用的一些方法:

案例:

使用AWT绘图API,完成下图效果

演示代码:

import java.awt.*;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import java.util.Random;public class SimpleDraw {private final String RECT_SHAPE="rect";private final String OVAL_SHAPE="oval";private Frame frame = new Frame("这里测试绘图");private Button drawRectBtn = new Button("绘制矩形");private Button drawOvalBtn = new Button("绘制椭圆");//用来保存当前用户需要绘制什么样的图形private String shape="";private MyCanvas drawArea = new MyCanvas();public void init(){//为按钮添加点击事件drawRectBtn.addActionListener(new ActionListener() {@Overridepublic void actionPerformed(ActionEvent e) {shape = RECT_SHAPE;drawArea.repaint();}});drawOvalBtn.addActionListener(new ActionListener() {@Overridepublic void actionPerformed(ActionEvent e) {shape = OVAL_SHAPE;drawArea.repaint();}});//定义一个Panel,装载两个按钮Panel p = new Panel();p.add(drawRectBtn);p.add(drawOvalBtn);//把panel添加到frame底部frame.add(p,BorderLayout.SOUTH);//设置画布的大小drawArea.setPreferredSize(new Dimension(300,200));//把画布添加到frame中frame.add(drawArea);frame.pack();frame.setVisible(true);}public static void main(String[] args) {new SimpleDraw().init();}//1.自定义类,继承Canvas类,重写paint方法private class MyCanvas extends Canvas{@Overridepublic void paint(Graphics g) {Random r = new Random();if (shape.equals(RECT_SHAPE)){//绘制矩形g.setColor(Color.BLACK);g.drawRect(r.nextInt(200),r.nextInt(100),40,60);}if(shape.equals(OVAL_SHAPE)){//绘制椭圆g.setColor(Color.RED);g.drawOval(r.nextInt(200),r.nextInt(100),60,40);}}}
}

Java也可用于开发一些动画。所谓动画,就是间隔一定的时间(通常小于0 . 1秒 )重新绘制新的图像,两次绘制的图像之间差异较小,肉眼看起来就成了所谓的动画 。

为了实现间隔一定的时间就重新调用组件的 repaint()方法,可以借助于 Swing 提供的Timer类,Timer类是一个定时器, 它有如下一个构造器 :Timer(int delay, ActionListener listener): 每间隔 delay 毫秒,系统自动触发 ActionListener 监听器里的事件处理器方法,在方法内部我们就可以调用组件的repaint方法,完成组件重绘。

案例2:

使用AWT画图技术及Timer定时器,完成下图中弹球小游戏。

演示代码2:

package awt_swimg.day03;import awt_swimg.day01.Utils;import javax.swing.*;
import java.awt.*;
import java.awt.event.*;public class PinBall {//桌面宽度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 ySpeed = 10;//小球横向运行速度private int xSpeed = 5;//定义小球的初始坐标private int ballX = 120;private int ballY = 20;//定义球拍的初始坐标,x坐标会发生变化,y坐标不会发生变化private int RACKET_X = 120;private final int RACKET_Y = 340;//声明定时器private Timer timer;private JFrame frame=new JFrame("弹球游戏");private MyCanvas canvas=new MyCanvas();//定义游戏结束的标记private boolean isLose = false;private KeyListener event = new KeyAdapter() {@Overridepublic void keyPressed(KeyEvent e) {int keyCode = e.getKeyCode();if (keyCode == KeyEvent.VK_LEFT) {if (RACKET_X > 0) {RACKET_X -= 10;}}if (keyCode == KeyEvent.VK_RIGHT) {if (RACKET_X < TABLE_WIDTH - RACKET_WIDTH) {RACKET_X += 10;}}}};private ActionListener timerTask=new ActionListener() {@Overridepublic void actionPerformed(ActionEvent e) {if (ballX<=0||ballX>=TABLE_WIDTH-BALL_SIZE) {xSpeed=-xSpeed;}if (ballY<=0||ballY>=RACKET_Y-BALL_SIZE&&ballX>= RACKET_X &&ballX<= RACKET_X +RACKET_WIDTH) {ySpeed = -ySpeed;}if (ballY>RACKET_Y&&(ballX<RACKET_X||ballX>RACKET_X+RACKET_WIDTH)) {timer.stop();isLose=true;canvas.repaint();}ballX += xSpeed;ballY += ySpeed;canvas.repaint();}};private MenuBar menuBar=new MenuBar();private Menu option=new Menu("选项");private MenuItem reStart=new MenuItem("重新开始");private MenuItem exit=new MenuItem("退出");public void init(){frame.add(canvas);frame.setMenuBar(menuBar);menuBar.add(option);option.add(reStart);option.add(exit);exit.addActionListener(e -> System.exit(0));reStart.addActionListener(e -> {isLose=false;ballX = 120;ballY = 20;RACKET_X = 120;canvas.repaint();timer.start();});canvas.setPreferredSize(new Dimension(TABLE_WIDTH,TABLE_HEIGHT));canvas.addKeyListener(event);frame.addKeyListener(event);timer=new Timer(50,timerTask);timer.start();Utils.setJFrame(frame);}public static void main(String[] args) {new PinBall().init();}public class MyCanvas extends Canvas{@Overridepublic void paint(Graphics g) {if (isLose) {g.setColor(Color.BLUE);g.setFont(new Font("Times",Font.BOLD,30));g.drawString("游戏结束!",80,200);}else{g.setColor(Color.red);g.fillOval(ballX, ballY, BALL_SIZE, BALL_SIZE);g.setColor(Color.green);g.fillRect(RACKET_X, RACKET_Y, RACKET_WIDTH, RACKET_HEIGHT);}}}
}

http://www.lryc.cn/news/169576.html

相关文章:

  • uniapp滑动事件
  • 入门人工智能 —— 学习 python 使用 IDE :vscode 完成编程 (2)
  • MyBatis字段名和属性名不一样的解决方案
  • Postman应用——Collection、Folder和Request
  • 驱动开发,stm32mp157a开发板的led灯控制实验
  • 黑客入侵机构,导致2万条信息被卖
  • 循环购:让消费者和商家共赢的新型电商模式
  • 分布式缓冲-Redis
  • C# 流Stream详解(3)——FileStream源码
  • C语言的文件操作(炒详解)
  • 27.基于ADS的不等分威尔金森功分器设计
  • Linux自用命令
  • clickhouse union all之后数据量不一致
  • 力扣刷题19-删除链表的倒数第N个节点
  • Unity中的简单数据存储办法
  • Pytorch-MLP-CIFAR10
  • SQL2 查询多列
  • 算法分享三个方面学习方法(做题经验,代码编写经验,比赛经验)
  • 爬虫 — 验证码反爬
  • 视频图像处理算法opencv模块硬件设计图像颜色识别模块
  • 目标检测网络之Fast-RCNN
  • Golang Gorm 创建HOOK
  • 计算机视觉的应用15-图片旋转验证码的角度计算模型的应用,解决旋转图片矫正问题
  • 【Seata】分布式事务问题和理论基础
  • 文件打包解包的方法
  • npm 清缓存(重新安装node-modules)
  • sqlserver查询表中所有字段信息
  • 二叉树的概念、存储及遍历
  • 【面试题】智力题
  • 【SpringBoot集成Redis + Session持久化存储到Redis】