最近在做一个rpg小游戏,研究到粒子系统。粒子系统(particle system)是图形里常用的特效。粒子系统可应用运动学模拟来做到很多不同的效果。粒子系统在游戏和动画中,常常会用来做雨点、火花、烟、爆炸等等不同的视觉效果。
粒子系统模拟大量的粒子,并通常用某些方法把粒子渲染。粒子通常有以下特性:
粒子是独立的,粒子之间互不影响(不碰撞、没有力) 粒子有生命周期,生命结束后会消失 粒子可以理解为空间的一个点,有时候也可以设定半径作为球体和环境碰撞 粒子带有运动状态,也有其他外观状态(例如颜色、影像等) 粒子可以只有线性运动,而不考虑旋转运动(也有例外) 下图是本人实现的一个酷酷的粒子效果(截图效果不太好,实际运行效果好很多)。
当然你可以发挥你的想象力,制作更有意思的粒子效果。记得以前看到国外有的网站用的那种全像素点的验证码,其实思路差不多。实现代码如下:
粒子系统模拟大量的粒子,并通常用某些方法把粒子渲染。粒子通常有以下特性:
粒子是独立的,粒子之间互不影响(不碰撞、没有力) 粒子有生命周期,生命结束后会消失 粒子可以理解为空间的一个点,有时候也可以设定半径作为球体和环境碰撞 粒子带有运动状态,也有其他外观状态(例如颜色、影像等) 粒子可以只有线性运动,而不考虑旋转运动(也有例外) 下图是本人实现的一个酷酷的粒子效果(截图效果不太好,实际运行效果好很多)。
import java.awt.Font; import java.awt.Graphics; import java.awt.image.BufferedImage; import java.util.Iterator; import java.util.LinkedList; import java.util.List; import javafx.animation.AnimationTimer; import javafx.application.Application; import javafx.embed.swing.SwingFXUtils; import javafx.scene.Group; import javafx.scene.Scene; import javafx.scene.canvas.Canvas; import javafx.scene.canvas.GraphicsContext; import javafx.scene.image.PixelReader; import javafx.scene.image.WritableImage; import javafx.scene.paint.Color; import javafx.stage.Stage; public class SnowWord extends Application{ private Listsnow = new LinkedList<>(); double gravity = 0.15D; @Override public void start(Stage stage) throws Exception{ WritableImage image = new WritableImage(500, 400); drawString(image, "东方上人", 60, 200); final PixelReader reader = image.getPixelReader(); Canvas show = new Canvas(500, 400); final GraphicsContext context = show.getGraphicsContext2D(); new AnimationTimer(){ @Override public void handle(long arg0){ context.clearRect(0, 0, 500, 400); context.setFill(Color.BLACK); context.fillRect(0, 0, 500, 400); context.setFill(Color.WHITE); Iterator it = snow.iterator(); while(it.hasNext()){ Point p = it.next(); p.vy += gravity * p.s; p.y += p.vy; if(p.y >= 400){ it.remove(); }else{ /* 指定坐标处是否处在文字上 */ if(reader.getColor((int) p.x, (int) p.y).equals(Color.BLACK)){ p.y -= p.vy; p.vy = 0; p.y += 0.2; } context.fillOval(p.x, p.y, 2, 2); } } for(int i = 0; i < 10; i++){ snow.add(new Point(Math.random() * 500, 0, Math.random() + 0.5)); } } }.start(); Scene scene = new Scene(new Group(show)); stage.setScene(scene); stage.setTitle("粒子系统 - www.zhouhaocheng.cn"); stage.show(); } public void drawString(WritableImage image, String text, int x, int y){ BufferedImage buffer = SwingFXUtils.fromFXImage(image, null); Graphics g = buffer.getGraphics(); g.setColor(java.awt.Color.BLACK); g.setFont(new Font("Microsoft YaHei", 1, 100)); g.drawString(text, x, y); SwingFXUtils.toFXImage(buffer, image); g.dispose(); } public static void main(String[] args){ launch(args); } static class Point{ double x; // x坐标 double y; // y坐标 double s; // 下降加速度 double vy; // y轴方向速度 public Point(double x, double y, double s){ this.x = x; this.y = y; this.s = s; this.vy = 0; } public String toString(){ return x + " , " + y + " , " + s + " , " + vy; } } }
当然你可以发挥你的想象力,制作更有意思的粒子效果。记得以前看到国外有的网站用的那种全像素点的验证码,其实思路差不多。实现代码如下:
import java.awt.Color; import java.awt.Font; import java.awt.FontMetrics; import java.awt.Graphics2D; import java.awt.image.BufferedImage; import java.util.Random; public class NoisyCaptcha{ // 图片的宽度。 private int width = 120; // 图片的高度。 private int height = 40; private String fontName; private int fontStyle = 1; private int fontSize; private static String codes = "abcdefghijkmnpqrstuvwxyzABCDEFGHIJKLMNPQRSTUVWXYZ23456789"; public NoisyCaptcha(int width, int height){ this(width, height, "Microsoft YaHei", 1, height - 10); } public NoisyCaptcha(int width, int height, String fontName, int fontStyle, int fontSize){ this.width = width; this.height = height; this.fontName = fontName; this.fontStyle = fontStyle; this.fontSize = fontSize; } public BufferedImage genCode(String text){ BufferedImage image = new BufferedImage(width, height, BufferedImage.TYPE_INT_RGB); Graphics2D g = image.createGraphics(); g.setColor(Color.WHITE); g.fillRect(0, 0, width, height); g.setFont(new Font(fontName, fontStyle, fontSize)); FontMetrics fm = g.getFontMetrics(); g.setColor(Color.BLACK); g.drawString(text, width / 2 - fm.stringWidth(text) / 2, height / 2 + fm.getAscent() / 3); g.dispose(); BufferedImage result = new BufferedImage(width, height, BufferedImage.TYPE_INT_RGB); g = result.createGraphics(); g.setColor(Color.BLACK); g.fillRect(0, 0, width, height); g.setColor(Color.WHITE); for(int i = 0; i < width; i++){ for(int j = 0; j < height; j++){ double r = Math.random(); /* 如下0.65和0.95可根据实际显示效果调整 */ if(image.getRGB(i, j) == Color.BLACK.getRGB()){ if(r > 0.65) g.drawOval(i, j, 1, 1); }else if(r > 0.95){ g.drawOval(i, j, 1, 1); } } } g.dispose(); return result; } public static String generateTextCode(int verifySize){ int codesLen = codes.length(); Random rand = new Random(System.currentTimeMillis()); StringBuilder verifyCode = new StringBuilder(verifySize); for(int i = 0; i < verifySize; i++){ verifyCode.append(codes.charAt(rand.nextInt(codesLen - 1))); } return verifyCode.toString(); } }生成的验证码图片效果入下:
收藏的用户(0) X
正在加载信息~
推荐阅读
最新回复 (0)
站点信息
- 文章2300
- 用户1336
- 访客10860229
每日一句
True success inspires others to act.
真正的成功是激励他人行动。
真正的成功是激励他人行动。
语法错误: 意外的令牌“标识符”
全面理解Gradle - 定义Task
Motrix全能下载工具 (支持 BT / 磁力链 / 百度网盘)
谷歌Pixel正在开始起飞?
获取ElementUI Table排序后的数据
Run-Time Check Failure #0 - The value of ESP was not properly saved across a function call. This is
亲测!虚拟机VirtualBox安装MAC OS 10.12图文教程
华为手机app闪退重启界面清空log日志问题
android ndk开发之asm/page.h: not found
手机屏幕碎了怎么备份操作?
免ROOT实现模拟点击任意位置
新手必看修改DSDT教程
thinkpad t470p装黑苹果系统10.13.2
新会员