当前位置: 首页 > 工具软件 > Ren'Py > 使用案例 >

python粒子特效_Ren'Py引擎从入门到放弃(支线3)——简单粒子效果

鞠凌龙
2023-12-01

世上无难事,只要肯放弃。

支线系列是独立于基础之外的内容,会引用一些外部平台大佬的内容,感觉有困难的同学可以暂时不(fang)看(qi)。

本篇内容将讲解一个简单的粒子系统。请善用官方文档的搜索功能,能解决大部分疑问。

第一个问题:粒子是什么?

答:在大多数游戏引擎和动画设计软件中,都有一种叫做particle的对象,一般翻译成“粒子”。通常粒子都是小光点或者小图片,通常会设计成从某个发射点“出生”,经过一段时间之后“死亡”。

第二个问题:Ren'Py中如何使用粒子?

答:Ren'Py比较奇葩,自带的粒子系统不叫particle而是sprite……这很容易跟其他软件中的sprite(精灵)混淆。翻译文档的时候也挺纠结……

Ren'Py自带的Sprite和Spritemanager两个类,以及一个SnowBlossom函数。总体来说偏向底层,所以可以根据需要自己编写粒子效果。

这篇暂时不讲Ren'Py自带的这部分内容~

第三个问题:那说什么粒子?

答:以下内容参考了Ren'Py的Wiki上Particle Burst,以及lemmasoft论坛大佬Xela的帖子(他也贡献了Ren'Py引擎的部分代码)。

先上代码:

transform particle(d, delay, speed=1.0, around=(config.screen_width/2, config.screen_height/2), angle=0, radius=200):

d

pause delay

subpixel True

around around

radius 0

linear speed radius radius angle angle

init python:

class ParticleBurst(renpy.Displayable):

def __init__(self, displayable, interval=(0.02, 0.04), speed=(0.15, 0.3), around=(config.screen_width/2, config.screen_height/2), angle=(0, 360), radius=(50, 75), particles=None, mouse_sparkle_mode=False, **kwargs):

"""Creates a burst of displayable...

@params:

- displayable: Anything that can be shown in Ren'Py (expects a single displayable or a container of displayable to randomly draw from).

- interval: Time between bursts in seconds (expects a tuple with two floats to get randoms between them).

- speed: Speed of the particle (same rule as above).

- angle: Area delimiter (expects a tuple with two integers to get randoms between them) with full circle burst by default. (0, 180) for example will limit the burst only upwards creating sort of a fountain.

- radius: Distance delimiter (same rule as above).

- around: Position of the displayable (expects a tuple with x/y integers). Burst will be focused around this position.

- particles: Amount of particle to go through, endless by default.

- mouse_sparkle_mode: Focuses the burst around a mouse poiner overriding "around" property.

This is far better customizable than the original ParticleBurst and is much easier to expand further if an required..

"""

super(ParticleBurst, self).__init__(**kwargs)

self.d = [renpy.easy.displayable(d) for d in displayable] if isinstance(displayable, (set, list, tuple)) else [renpy.easy.displayable(displayable)]

self.interval = interval

self.speed = speed

self.around = around

self.angle = angle

self.radius = radius

self.particles = particles

self.msm = mouse_sparkle_mode

def render(self, width, height, st, at):

rp = store.renpy

if not st:

self.next = 0

self.particle = 0

self.shown = {}

render = rp.Render(width, height)

if not (self.particles and self.particle >= self.particles) and self.next <= st:

speed = rp.random.uniform(self.speed[0], self.speed[1])

angle = rp.random.randrange(self.angle[0], self.angle[1])

radius = rp.random.randrange(self.radius[0], self.radius[1])

if not self.msm:

self.shown[st + speed] = particle(rp.random.choice(self.d), st, speed, self.around, angle, radius)

else:

self.shown[st + speed] = particle(rp.random.choice(self.d), st, speed, rp.get_mouse_pos(), angle, radius)

self.next = st + rp.random.uniform(self.interval[0], self.interval[1])

if self.particles:

self.particle = self.particle + 1

for d in self.shown.keys():

if d < st:

del(self.shown[d])

else:

d = self.shown[d]

render.blit(d.render(width, height, st, at), (d.xpos, d.ypos))

rp.redraw(self, 0)

return render

def visit(self):

return self.d

这段代码的风格比较……古典~开头的变换(transform)是我们可以根据自己需求修改的部分。后面大段Python语句可以不管,反正能用就行……然后使用下面的脚本就可以显示效果了:

# 定义粒子元素,particle.png是要使用的例子图片

image particle = "particle.png"

# 定义粒子喷射图像

image boom = ParticleBurst("particle", mouse_sparkle_mode=False)

# 在某段脚本中显示粒子喷射图像

label start:

show boom

效果如图。

很明显,粒子是顺时针螺旋型喷射的。也就是说,单个粒子只是随着时间变化,不断增加自身特性(property)中radius和angle的值。如果我们修改一部分内容,就可以实现类似烟花的效果:

image boom = ParticleBurst("particle", speed=(0.15, 0.5), angle=(-90, 90), radius=(50,200))

当然,这里的particle参数是一切可视组件(displayable),所以我们还可以用图像处理器或者ATL制造各种效果。比如我把图片换掉,然后用im.MatrixColor制造色调分离效果:

image particle colored = im.MatrixColor(

"particle.png",

im.matrix.colorize("#ff4a12", "#ffcfac"))

预告部分:可能会有一个补充章节……

 类似资料: