过年必备Java动态烟花教程如何用Canvas和Timer实现炫酷烟花动画
cac55 2024-09-27 07:12 22 浏览 0 评论
烟花是一种常见的庆祝活动和节日的方式,它们在夜空中绽放出各种颜色和形状,给人们带来美丽和欢乐。你是否想过用Java编程来模拟烟花的效果呢?如果你对此感兴趣,那么这篇教程就是为你准备的。在这篇教程中,你将学习如何用Java的Canvas和Timer类来创建一个简单的烟花动画,让你的程序也能展现出烟花的魅力。
教程目标
在这篇教程中,你将完成以下目标:
- 创建一个Canvas类的对象,用于绘制烟花的图形
- 创建一个Firework类的对象,用于表示一个烟花的属性和行为
- 创建一个Timer类的对象,用于控制烟花的运动和爆炸
- 创建一个ArrayList类的对象,用于存储多个烟花的对象
- 在Canvas上随机生成和显示多个烟花的对象,并让它们按照一定的规律运动和爆炸
- 在IntelliJ环境中运行和测试你的程序,并观察烟花的效果
教程准备
在开始这篇教程之前,你需要准备以下内容:
- 一台安装了Java开发环境的电脑,推荐使用Java 8或以上的版本
- 一个安装了IntelliJ IDEA的电脑,推荐使用最新的版本
- 一些基本的Java编程知识,例如变量,数据类型,类,对象,方法,数组,集合,循环,条件,异常等
- 一些基本的Java图形编程知识,例如Canvas,Graphics,Color,Font等
教程步骤
接下来,我们将按照以下步骤来完成这篇教程:
步骤一:创建一个Canvas类的对象
Canvas是Java中用于绘制图形的一个类,它提供了一个画布,可以在上面绘制各种图形,例如线,矩形,圆,文字等。为了在我们的程序中使用Canvas,我们需要创建一个Canvas类的对象,并设置它的一些属性,例如大小,背景色,字体等。我们还需要创建一个JFrame类的对象,用于创建一个窗口,将Canvas添加到窗口中,并设置窗口的一些属性,例如标题,大小,位置,关闭方式等。以下是创建Canvas类的对象和JFrame类的对象的代码:
import javax.swing.*;
import java.awt.*;
public class FireworkCanvas extends Canvas {
// 定义画布的宽度和高度
public static final int WIDTH = 800;
public static final int HEIGHT = 600;
// 定义画布的背景色和字体
public static final Color BACKGROUND = Color.BLACK;
public static final Font FONT = new Font("Arial", Font.BOLD, 20);
// 定义一个JFrame类的对象,用于创建窗口
private JFrame frame;
// 定义一个构造方法,用于初始化画布和窗口
public FireworkCanvas() {
// 调用父类的构造方法,设置画布的大小
super();
setSize(WIDTH, HEIGHT);
// 设置画布的背景色和字体
setBackground(BACKGROUND);
setFont(FONT);
// 创建一个JFrame类的对象,用于创建窗口
frame = new JFrame();
// 将画布添加到窗口中
frame.add(this);
// 设置窗口的标题,大小,位置,关闭方式等
frame.setTitle("Java动态烟花教程");
frame.pack();
frame.setLocationRelativeTo(null);
frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
// 显示窗口
frame.setVisible(true);
}
}
在上面的代码中,我们首先导入了javax.swing和java.awt两个包,这两个包包含了我们需要用到的一些类,例如JFrame,Canvas,Graphics,Color,Font等。然后,我们定义了一个FireworkCanvas类,它继承了Canvas类,表示它是一个画布。在这个类中,我们定义了一些常量,用于表示画布的宽度,高度,背景色,字体等。我们还定义了一个JFrame类的对象,用于表示一个窗口。接着,我们定义了一个构造方法,用于初始化画布和窗口。在这个方法中,我们调用了父类的构造方法,设置了画布的大小,背景色,字体等。然后,我们创建了一个JFrame类的对象,将画布添加到窗口中,并设置了窗口的标题,大小,位置,关闭方式等。最后,我们调用了setVisible方法,让窗口显示出来。
步骤二:创建一个Firework类的对象
Firework是我们自定义的一个类,用于表示一个烟花的属性和行为。一个烟花的对象有以下的属性:
- x坐标,表示烟花的水平位置
- y坐标,表示烟花的垂直位置
- x速度,表示烟花的水平速度
- y速度,表示烟花的垂直速度
- 颜色,表示烟花的颜色
- 半径,表示烟花的大小
- 状态,表示烟花的状态,有三种状态:上升,爆炸,消失
- 粒子,表示烟花爆炸后的粒子,是一个Firework类的对象的数组
一个烟花的对象有以下的行为:
- 构造方法,用于初始化烟花的属性
- update方法,用于更新烟花的位置,速度,状态,粒子等
- render方法,用于绘制烟花的图形
- isAlive方法,用于判断烟花是否还存活
以下是创建Firework类的对象的代码:
import java.awt.*;
import java.util.Random;
public class Firework {
// 定义一个Random类的对象,用于生成随机数
private static final Random random = new Random();
// 定义一些常量,用于表示烟花的状态
private static final int RISING = 0; // 上升
private static final int EXPLODING = 1; // 爆炸
private static final int FADING = 2; // 消失
// 定义一些常量,用于表示烟花的物理参数
private static final double GRAVITY = 0.1; // 重力
private static final double FRICTION = 0.99; // 摩擦力
private static final double LIFESPAN = 0.8; // 粒子的寿命
// 定义烟花的属性
private double x; // x坐标
private double y; // y坐标
private double vx; // x速度
private double vy; // y速度
private Color color; // 颜色
private int radius; // 半径
private int state; // 状态
private Firework[] particles; // 粒子
// 定义一个构造方法,用于初始化烟花的属性
public Firework(double x, double y, double vx, double vy, Color color, int radius, int state) {
// 将参数赋值给属性
this.x = x;
this.y = y;
this.vx = vx;
this.vy = vy;
this.color = color;
this.radius = radius;
this.state = state;
// 如果状态是爆炸,那么创建粒子数组
if (state == EXPLODING) {
// 随机生成粒子的数量,范围是10到50
int num = random.nextInt(41) + 10;
// 创建一个Firework类的对象的数组,用于存储粒子
particles = new Firework[num];
// 遍历粒子数组,为每个粒子赋值
for (int i = 0; i < num; i++) {
// 随机生成粒子的x速度,范围是-5到5
double pvx = random.nextDouble() * 10 - 5;
// 随机生成粒子的y速度,范围是-5到5
double pvy = random.nextDouble() * 10 - 5;
// 随机生成粒子的颜色,可以和烟花的颜色相同,也可以不同
Color pcolor = random.nextBoolean() ? color : new Color(random.nextInt(256), random.nextInt(256), random.nextInt(256));
// 随机生成粒子的半径,范围是1到3
int pradius = random.nextInt(3) + 1;
// 创建一个Firework类的对象,表示一个粒子,状态是消失
Firework particle = new Firework(x, y, pvx, pvy, pcolor, pradius, FADING);
// 将粒子对象存入粒子数组
particles[i] = particle;
}
}
}
在上面的代码中,我们定义了一个Firework类,用于表示一个烟花的属性和行为。在这个类中,我们定义了一些常量,用于表示烟花的状态,物理参数等。我们还定义了一些属性,用于表示烟花的位置,速度,颜色,大小,状态,粒子等。接着,我们定义了一个构造方法,用于初始化烟花的属性。在这个方法中,我们将参数赋值给属性,并根据状态是否是爆炸,来决定是否创建粒子数组。如果状态是爆炸,那么我们随机生成一些粒子的属性,并创建一个Firework类的对象的数组,用于存储粒子。这样,我们就完成了烟花对象的创建。
步骤三:更新烟花的对象
为了让烟花的对象能够动起来,我们需要更新它们的位置,速度,状态,粒子等。我们可以定义一个update方法,用于实现这个功能。在这个方法中,我们需要根据烟花的状态,来执行不同的操作。以下是update方法的代码:
// 定义一个update方法,用于更新烟花的位置,速度,状态,粒子等
public void update() {
// 根据烟花的状态,执行不同的操作
switch (state) {
case RISING: // 如果状态是上升
// 更新烟花的位置,根据速度和时间的关系
x += vx;
y += vy;
// 更新烟花的速度,根据重力和摩擦力的影响
vx *= FRICTION;
vy = (vy + GRAVITY) * FRICTION;
// 判断烟花是否达到最高点,根据y速度的符号
if (vy >= 0) {
// 如果达到最高点,那么改变烟花的状态为爆炸,并创建一个新的烟花对象,表示爆炸后的烟花
state = EXPLODING;
Firework explosion = new Firework(x, y, 0, 0, color, radius, EXPLODING);
// 将新的烟花对象赋值给当前的烟花对象,覆盖原来的属性
this.x = explosion.x;
this.y = explosion.y;
this.vx = explosion.vx;
this.vy = explosion.vy;
this.color = explosion.color;
this.radius = explosion.radius;
this.state = explosion.state;
this.particles = explosion.particles;
}
break;
case EXPLODING: // 如果状态是爆炸
// 遍历粒子数组,更新每个粒子的位置,速度,状态等
for (Firework particle : particles) {
particle.update();
}
break;
case FADING: // 如果状态是消失
// 更新烟花的半径,根据寿命的衰减
radius *= LIFESPAN;
break;
}
}
在上面的代码中,我们定义了一个update方法,用于更新烟花的位置,速度,状态,粒子等。在这个方法中,我们根据烟花的状态,执行不同的操作。如果状态是上升,那么我们根据速度和时间的关系,更新烟花的位置。然后,我们根据重力和摩擦力的影响,更新烟花的速度。接着,我们判断烟花是否达到最高点,根据y速度的符号。如果达到最高点,那么我们改变烟花的状态为爆炸,并创建一个新的烟花对象,表示爆炸后的烟花。然后,我们将新的烟花对象赋值给当前的烟花对象,覆盖原来的属性。这样,我们就完成了烟花的上升和爆炸的过程。
如果状态是爆炸,那么我们遍历粒子数组,更新每个粒子的位置,速度,状态等。我们可以调用粒子对象的update方法,来实现这个功能。这样,我们就完成了烟花的爆炸和粒子的运动的过程。
如果状态是消失,那么我们更新烟花的半径,根据寿命的衰减。我们可以乘以一个小于1的常数,来模拟烟花的半径的缩小。这样,我们就完成了烟花的消失的过程。
步骤四:绘制烟花的对象
为了让烟花的对象能够显示出来,我们需要绘制它们的图形。我们可以定义一个render方法,用于实现这个功能。在这个方法中,我们需要根据烟花的状态,来执行不同的操作。以下是render方法的代码:
// 定义一个render方法,用于绘制烟花的图形
public void render(Graphics g) {
// 根据烟花的状态,执行不同的操作
switch (state) {
case RISING: // 如果状态是上升
// 设置画笔的颜色为烟花的颜色
g.setColor(color);
// 绘制一个实心圆,表示烟花的图形,根据烟花的位置和半径
g.fillOval((int) x - radius, (int) y - radius, radius * 2, radius * 2);
break;
case EXPLODING: // 如果状态是爆炸
// 遍历粒子数组,绘制每个粒子的图形
for (Firework particle : particles) {
particle.render(g);
}
break;
case FADING: // 如果状态是消失
// 设置画笔的颜色为烟花的颜色,但是透明度随着半径的减小而减小
g.setColor(new Color(color.getRed(), color.getGreen(), color.getBlue(), (int) (radius * 255 / 3)));
// 绘制一个实心圆,表示烟花的图形,根据烟花的位置和半径
g.fillOval((int) x - radius, (int) y - radius, radius * 2, radius * 2);
break;
}
}
在上面的代码中,我们定义了一个render方法,用于绘制烟花的图形。在这个方法中,我们根据烟花的状态,执行不同的操作。如果状态是上升,那么我们设置画笔的颜色为烟花的颜色,并绘制一个实心圆,表示烟花的图形,根据烟花的位置和半径。这样,我们就完成了烟花的上升的绘制。
如果状态是爆炸,那么我们遍历粒子数组,绘制每个粒子的图形。我们可以调用粒子对象的render方法,来实现这个功能。这样,我们就完成了烟花的爆炸和粒子的绘制。
如果状态是消失,那么我们设置画笔的颜色为烟花的颜色,但是透明度随着半径的减小而减小,并绘制一个实心圆,表示烟花的图形,根据烟花的位置和半径。这样,我们就完成了烟花的消失的绘制
步骤五:在IntelliJ环境中运行和测试你的程序,并观察烟花的效果
现在,我们已经完成了Firework类和FireworkCanvas类的编写,我们可以在IntelliJ环境中运行和测试我们的程序,并观察烟花的效果。以下是在IntelliJ环境中运行和测试你的程序的步骤:
- 打开IntelliJ IDEA,创建一个新的Java项目,命名为FireworkTutorial
- 在src文件夹下,创建两个新的Java类,分别命名为Firework和FireworkCanvas,并将我们之前编写的代码复制到相应的类中
- 在FireworkCanvas类中,添加一个main方法,用于启动程序
- 在main方法中,创建一个FireworkCanvas类的对象,用于创建画布和窗口
- 在FireworkCanvas类中,重写paint方法,用于绘制画布上的内容
- 在paint方法中,创建一个Graphics类的对象,用于绘制图形
- 在paint方法中,创建一个ArrayList类的对象,用于存储多个烟花的对象
- 在paint方法中,创建一个Timer类的对象,用于控制烟花的运动和爆炸
- 在paint方法中,创建一个TimerTask类的对象,用于实现定时任务
- 在TimerTask类的对象中,重写run方法,用于执行定时任务
- 在run方法中,随机生成一个烟花的对象,并添加到烟花的数组中
- 在run方法中,遍历烟花的数组,更新和绘制每个烟花的对象
- 在run方法中,清除画布上的内容,重新绘制画布上的内容
- 在paint方法中,调用Timer类的对象的schedule方法,用于启动定时任务
- 在IntelliJ环境中,运行FireworkCanvas类,观察窗口上的烟花的效果
以下是在IntelliJ环境中运行和测试你的程序的代码:
import javax.swing.*;
import java.awt.*;
import java.util.ArrayList;
import java.util.Random;
import java.util.Timer;
import java.util.TimerTask;
public class FireworkCanvas extends Canvas {
// 定义画布的宽度和高度
public static final int WIDTH = 800;
public static final int HEIGHT = 600;
// 定义画布的背景色和字体
public static final Color BACKGROUND = Color.BLACK;
public static final Font FONT = new Font("Arial", Font.BOLD, 20);
// 定义一个JFrame类的对象,用于创建窗口
private JFrame frame;
// 定义一个构造方法,用于初始化画布和窗口
public FireworkCanvas() {
// 调用父类的构造方法,设置画布的大小
super();
setSize(WIDTH, HEIGHT);
// 设置画布的背景色和字体
setBackground(BACKGROUND);
setFont(FONT);
// 创建一个JFrame类的对象,用于创建窗口
frame = new JFrame();
// 将画布添加到窗口中
frame.add(this);
// 设置窗口的标题,大小,位置,关闭方式等
frame.setTitle("Java动态烟花教程");
frame.pack();
frame.setLocationRelativeTo(null);
frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
// 显示窗口
frame.setVisible(true);
}
// 定义一个main方法,用于启动程序
public static void main(String[] args) {
// 创建一个FireworkCanvas类的对象,用于创建画布和窗口
FireworkCanvas canvas = new FireworkCanvas();
}
// 重写paint方法,用于绘制画布上的内容
@Override
public void paint(Graphics g) {
// 创建一个Graphics类的对象,用于绘制图形
Graphics2D g2d = (Graphics2D) g;
// 创建一个ArrayList类的对象,用于存储多个烟花的对象
ArrayList<Firework> fireworks = new ArrayList<>();
// 创建一个Timer类的对象,用于控制烟花的运动和爆炸
Timer timer = new Timer();
// 创建一个TimerTask类的对象,用于实现定时任务
TimerTask task = new TimerTask() {
// 定义一个Random类的对象,用于生成随机数
private Random random = new Random();
// 重写run方法,用于执行定时任务
@Override
public void run() {
// 随机生成一个烟花的对象,并添加到烟花的数组中
double x = random.nextDouble() * WIDTH; // 随机生成烟花的x坐标,范围是0到画布的宽度
double y = HEIGHT; // 设置烟花的y坐标为画布的高度
double vx = random.nextDouble() * 10 - 5; // 随机生成烟花的x速度,范围是-5到5
double vy = -(random.nextDouble() * 10 + 10); // 随机生成烟花的y速度,范围是-20到-10
Color color = new Color(random.nextInt(256), random.nextInt(256), random.nextInt(256)); // 随机生成烟花的颜色
int radius = random.nextInt(5) + 5; // 随机生成烟花的半径,范围是5到10
int state = Firework.RISING; // 设置烟花的状态为上升
Firework firework = new Firework(x, y, vx, vy, color, radius, state); // 创建一个Firework类的对象,表示一个烟花
fireworks.add(firework); // 将烟花对象添加到烟花数组中
// 遍历烟花的数组,更新和绘制每个烟花的对象
for (int i = 0; i < fireworks.size(); i++) {
// 获取烟花的对象
Firework f = fireworks.get(i);
// 更新烟花的对象
f.update();
// 绘制烟花的对象
f.render(g2d);
// 判断烟花是否还存活
if (!f.isAlive()) {
// 如果不存活,那么从烟花的数组中移除
fireworks.remove(i);
i--;
}
}
// 清除画布上的内容,重新绘制画布上的内容
repaint();
}
};
// 调用Timer类的对象的schedule方法,用于启动定时任务
timer.schedule(task, 0, 50); // 每隔50毫秒执行一次定时任务
}
}
在上面的代码中,我们在FireworkCanvas类中添加了一个main方法,用于启动程序。在这个方法中,我们创建了一个FireworkCanvas类的对象,用于创建画布和窗口。然后,我们重写了paint方法,用于绘制画布上的内容。在这个方法中,我们创建了一个Graphics类的对象,用于绘制图形。然后,我们创建了一个ArrayList类的对象,用于存储多个烟花的对象。接着,我们创建了一个Timer类的对象,用于控制烟花的运动和爆炸。然后,我们创建了一个TimerTask类的对象,用于实现定时任务。在这个对象中,我们重写了run方法,用于执行定时任务。在这个方法中,我们随机生成一个烟花的对象,并添加到烟花的数组中。然后,我们遍历烟花的数组,更新和绘制每个烟花的对象。最后,我们清除画布上的内容,重新绘制画布上的内容。最后,我们调用了Timer类的对象的schedule方法,用于启动定时
相关推荐
- 无力吐槽的自动续费(你被自动续费困扰过吗?)
-
今天因为工作需要,需要在百度文库上下载一篇文章。没办法,确实需要也有必要,只能老老实实的按要求买了个VIP。过去在百度文库上有过类似经历,当时为了写论文买了一个月的VIP,后面也没有太注意,直到第二个...
- 百度文库推出“文源计划”创作者可一键认领文档
-
11月7日,百度文库发布了旨在保护创作者权益的“文源计划”。所谓“文源计划”,即为每一篇文档找到源头,让创作者享受更多的权益。据百度文库总经理李小婉介绍,文源计划分为三部分,分别是版权认证、版权扶持和...
- 有开放大学学号的同学,百度文库高校版可以用了。
-
还在网上找百度文库的下载方式,只要从身边的朋友在读开放大学的,那他(她)的学号就可以登陆到国家开放大学图书馆,还使用百度文库高校版来下载。与百度文库稍有不同,但足够使用了。现转国图链接如下:htt...
- 搜索资源方法推荐(搜索资源的方法)
-
今天msgbox就要教大家如何又快又准的搜到各类资源,第一点,排除干扰百度搜索出来啊经常前排展示它的产品以及百度文库,如何去除呢?很简单,后面输入空格减号百度文库,比如你搜高等数学百度文库很多,只要后...
- 一行代码搞定百度文库VIP功能(2021百度文库vip账号密码共享)
-
百度文库作为大家常用查资料找文档的平台,大多数文档我们都可以直接在百度文库找到,然而百度文库也有让人头痛的时候。好不容易找到一篇合适的文档,当你准备复制的时候他却提示你需要开通VIP才能复制~~~下载...
- 百度文库文档批量上传工具用户说明书
-
百度文库文档批量上传工具用户说明书1、软件主要功能1、批量上传文档到百度文库,支持上传到收费、VIP专享、优享以及共享。2、支持自动分类和自动获取标签3、支持多用户切换,一个账户传满可以切换到...
- 百度文库现在都看不到文档是否上传成功,要凉了吗?
-
打开知识店铺,百度文库文档里显示都是下载这一按键,上传的文档也看不到是否成功?咋情况,要取消了吗?没通过审核的也不让你删除,是几个意思,想通吃吗?现在百度上传文档也很费劲,有时弄了半天的资料上传审核过...
- 微信推广引流108式:利用百度文库长期分享软文引流
-
百度文库相对于百度知道、百度百科来说,操作上没那么多条条框框,规则上也相对好把握些。做一条百度知道所花费的精力一般都会比做一条百度文库的要多些,老马个人操作下来觉得百度文库更好把握。但见仁见智吧,今天...
- 职场“避雷”指南 百度文库推出标准化劳动合同范本
-
轰轰烈烈的毕业季结束了,众多应届生在经过了“职场海选”后,已正式成为职场生力军的一员。这一阶段,除了熟悉业务,签订劳动合同、了解职场福利也迅速被提上日程。而随着国人法律意识的增强,百度文库内《劳动合同...
- 《百度文库》:素材精选宝库(百度文库官网首页)
-
《百度文库》:独特功能助力选择高质量素材在当今信息爆炸的时代,如何高效地获取并利用有价值的素材成为了许多人面临的挑战。而《百度文库》作为百度公司推出的一款在线文档分享平台,凭借其丰富的资源、强大的功能...
- 深度整合和开放AI能力 百度文库和网盘推出内容操作系统「沧舟OS」
-
【TechWeb】4月25日消息,Create2025百度AI开发者大会上,百度文库和百度网盘推出全球首个内容操作系统——沧舟OS。基于沧舟OS,百度文库APP全新上线「GenFlow超能搭子」...
- 女子发现大二作业被百度文库要求付费下载,律师:平台侵权,应赔偿
-
近日,28岁的黎女士在百度百科搜索家乡的小地名时,发现了自己在大二完成的课题作业。她继续搜索,发现多个平台收录了该文,比如豆丁网和文档之家等,有的还设置了付费或积分下载。2月15日,九派新闻记者以用户...
- 2016杀入百度文库的新捷径,只有少数人才知道的喔
-
百度的产品在SEO优化中的分量真不用多说,其实很多人都像我一样一直在找捷径。但是我经常发现很多人都是在用死方法。比如发贴吧发帖而不知道去申请一个吧主,知道自问自答而不知道去申请一个合作资格。口碑和贴吧...
- 百度文库付费文档搜索方法(百度文库付费文档搜索方法有哪些)
-
一直以来,百度文库中无论是个人中心还是个人主页,都没有像淘宝一样的店内搜索功能,连最近新开的知识店铺也没有设计店内搜索功能,这无论是对上传用户还是下载用户都不方便,上传用户想要搜索自己的文档无法办到...
- 供读者免费使用!泰达图书馆机构版百度文库新年上新啦
-
在泰达图书馆读者使用百度文库数字资源不需要VIP,免-费-用!惊不惊喜?快来了解一下吧……新年伊始,为满足区域企业、高校、科研院所以及居民群众在教学、科研及学习过程中,对各类文献资源的需求,泰达图书馆...
你 发表评论:
欢迎- 一周热门
- 最近发表
- 标签列表
-
- 如何绘制折线图 (52)
- javaabstract (48)
- 新浪微博头像 (53)
- grub4dos (66)
- s扫描器 (51)
- httpfile dll (48)
- ps实例教程 (55)
- taskmgr (51)
- s spline (61)
- vnc远程控制 (47)
- 数据丢失 (47)
- wbem (57)
- flac文件 (72)
- 网页制作基础教程 (53)
- 镜像文件刻录 (61)
- ug5 0软件免费下载 (78)
- debian下载 (53)
- ubuntu10 04 (60)
- web qq登录 (59)
- 笔记本变成无线路由 (52)
- flash player 11 4 (50)
- 右键菜单清理 (78)
- cuteftp 注册码 (57)
- ospf协议 (53)
- ms17 010 下载 (60)