当前位置:   article > 正文

小学生python游戏编程arcade----烟花粒子_colorvalue = union[color, int, str, tuple[int, int

colorvalue = union[color, int, str, tuple[int, int, int], rgbaoutput, sequen

前言

接上篇文章继续解绍arcade游戏编程的基本知识。粒子系统

烟花粒子

1、Vector向量类

1.1 arcade中的向量类

RGB = Union[Tuple[int, int, int], List[int]]
RGBA = Union[Tuple[int, int, int, int], List[int]]
Color = Union[RGB, RGBA]
Point = Union[Tuple[float, float], List[float]]
NamedPoint = namedtuple(“NamedPoint”, [“x”, “y”])

Vector = Point

1.2 应用
def __init__(
        self,
        filename_or_texture: arcade.FilenameOrTexture,
        change_xy: Vector,
  • 1
  • 2
  • 3
  • 4

2、绘制粒子所有纹理图片

2.1 给定直径和颜色的圆的纹理

SPARK_textures = [arcade.make_circle_texture(6, clr) for clr in Color_list]

2.2 arcade.make_circle_texture函数原码
def make_circle_texture(diameter: int, color: Color, name: str = None) -> Texture:
    """
    返回具有给定直径和颜色的圆的纹理
    """

    name = name or _build_cache_name("circle_texture", diameter, color[0], color[1], color[2])

    bg_color = (0, 0, 0, 0)  # fully transparent
    img = PIL.Image.new("RGBA", (diameter, diameter), bg_color)
    draw = PIL.ImageDraw.Draw(img)
    draw.ellipse((0, 0, diameter - 1, diameter - 1), fill=color)
    return Texture(name, img)
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
2.3 make_soft_circle_texture 函数原码
def make_soft_circle_texture(diameter: int, color: Color, center_alpha: int = 255, outer_alpha: int = 0,
                             name: str = None) -> Texture:
    """
    Return a :class:`Texture` of a circle with the given diameter and color, fading out at its edges.

    :param int diameter: Diameter of the circle and dimensions of the square :class:`Texture` returned.
    :param Color color: Color of the circle.
    :param int center_alpha: Alpha value of the circle at its center.
    :param int outer_alpha: Alpha value of the circle at its edges.
    :param str name: Custom or pre-chosen name for this texture

    :returns: New :class:`Texture` object.
    :rtype: arcade.Texture
    """
    # TODO: create a rectangle and circle (and triangle? and arbitrary poly where client passes
    # in list of points?) particle?
    name = name or _build_cache_name("soft_circle_texture", diameter, color[0], color[1], color[2], center_alpha,
                                     outer_alpha)  # name must be unique for caching

    bg_color = (0, 0, 0, 0)  # fully transparent
    img = PIL.Image.new("RGBA", (diameter, diameter), bg_color)
    draw = PIL.ImageDraw.Draw(img)
    max_radius = int(diameter // 2)
    center = max_radius  # for readability
    for radius in range(max_radius, 0, -1):
        alpha = int(lerp(center_alpha, outer_alpha, radius / max_radius))
        clr = (color[0], color[1], color[2], alpha)
        draw.ellipse((center - radius, center - radius, center + radius - 1, center + radius - 1), fill=clr)

    return Texture(name, img)
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16
  • 17
  • 18
  • 19
  • 20
  • 21
  • 22
  • 23
  • 24
  • 25
  • 26
  • 27
  • 28
  • 29
  • 30
2.4 公共纹理代码
Color_list = (  # rainbon 彩虹
    arcade.color.ELECTRIC_CRIMSON,
    arcade.color.FLUORESCENT_ORANGE,
    arcade.color.ELECTRIC_YELLOW,
    arcade.color.ELECTRIC_GREEN,
    arcade.color.ELECTRIC_CYAN,
    arcade.color.MEDIUM_ELECTRIC_BLUE,
    arcade.color.ELECTRIC_INDIGO,
    arcade.color.ELECTRIC_PURPLE,
)

SPARK_textures = [arcade.make_circle_texture(6, clr) for clr in Color_list]
# 火花_对
SPARK_list = [
    [SPARK_textures[0], SPARK_textures[3]],
    [SPARK_textures[1], SPARK_textures[5]],
    [SPARK_textures[7], SPARK_textures[2]],
]
ROCKET_smoke_texture = arcade.make_soft_circle_texture(15, arcade.color.GRAY)
PUFF_texture = arcade.make_soft_circle_texture(80, (40, 40, 40))
FLASH_texture = arcade.make_soft_circle_texture(70, (128, 128, 90))
# 云 纹理
CLOUD_textures = [
    arcade.make_soft_circle_texture(50, arcade.color.WHITE),
    arcade.make_soft_circle_texture(50, arcade.color.LIGHT_GRAY),
    arcade.make_soft_circle_texture(50, arcade.color.LIGHT_BLUE),
]
# 星星 纹理
STAR_textures = [
    arcade.make_soft_circle_texture(8, arcade.color.WHITE),
    arcade.make_soft_circle_texture(8, arcade.color.PASTEL_YELLOW),
]
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16
  • 17
  • 18
  • 19
  • 20
  • 21
  • 22
  • 23
  • 24
  • 25
  • 26
  • 27
  • 28
  • 29
  • 30
  • 31
  • 32

3 效果图

在这里插入图片描述
在这里插入图片描述

在这里插入图片描述
粒子大小改大后
在这里插入图片描述

4 代码

"""
粒子焰花
使用焰火展示演示发射器和粒子的“真实世界”用途
"""
import arcade
from arcade import Point, Vector
from arcade.utils import _Vec2  # bring in "private" class
import os
import random
import pyglet

SCREEN_width = 800
SCREEN_height = 600

Color_list = (  # rainbon 彩虹
    arcade.color.ELECTRIC_CRIMSON,
    arcade.color.FLUORESCENT_ORANGE,
    arcade.color.ELECTRIC_YELLOW,
    arcade.color.ELECTRIC_GREEN,
    arcade.color.ELECTRIC_CYAN,
    arcade.color.MEDIUM_ELECTRIC_BLUE,
    arcade.color.ELECTRIC_INDIGO,
    arcade.color.ELECTRIC_PURPLE,
)

SPARK_textures = [arcade.make_circle_texture(6, clr) for clr in Color_list]
# 火花_对
SPARK_list = [
    [SPARK_textures[0], SPARK_textures[3]],
    [SPARK_textures[1], SPARK_textures[5]],
    [SPARK_textures[7], SPARK_textures[2]],
]
ROCKET_smoke_texture = arcade.make_soft_circle_texture(15, arcade.color.GRAY)
PUFF_texture = arcade.make_soft_circle_texture(80, (40, 40, 40))
FLASH_texture = arcade.make_soft_circle_texture(70, (128, 128, 90))
# 云 纹理
CLOUD_textures = [
    arcade.make_soft_circle_texture(50, arcade.color.WHITE),
    arcade.make_soft_circle_texture(50, arcade.color.LIGHT_GRAY),
    arcade.make_soft_circle_texture(50, arcade.color.LIGHT_BLUE),
]
# 星星 纹理
STAR_textures = [
    arcade.make_soft_circle_texture(8, arcade.color.WHITE),
    arcade.make_soft_circle_texture(8, arcade.color.PASTEL_YELLOW),
]
# 旋转器 高
SPINNER_height = 75

# 旋转器  emitter 发射器
def make_spinner():
    spinner = arcade.Emitter(
        center_xy=(SCREEN_width / 2, SPINNER_height - 5),
        emit_controller=arcade.EmitterIntervalWithTime(0.025, 2.0),
        particle_factory=lambda emitter: arcade.FadeParticle(
            filename_or_texture=random.choice(STAR_textures),
            change_xy=(0, 6.0),
            lifetime=0.2
        )
    )
    spinner.change_angle = 16.28
    return spinner


def make_rocket(emit_done_cb):
    """当烟花炮弹升入天空时显示烟雾轨迹的发射器"""
    rocket = RocketEmitter(
        center_xy=(random.uniform(100, SCREEN_width - 100), 25),
        emit_controller=arcade.EmitterIntervalWithTime(0.04, 2.0),
        particle_factory=lambda emitter: arcade.FadeParticle(
            filename_or_texture=ROCKET_smoke_texture,
            change_xy=arcade.rand_in_circle((0.0, 0.0), 0.08),
            scale=0.5,
            lifetime=random.uniform(1.0, 1.5),
            start_alpha=100,
            end_alpha=0,
            mutation_callback=rocket_smoke_mutator
        ),
        emit_done_cb=emit_done_cb
    )
    rocket.change_x = random.uniform(-1.0, 1.0) #
    rocket.change_y = random.uniform(5.0, 7.25)
    return rocket


def make_flash(prev_emitter):
    """当烟花炮弹爆炸时显示短暂闪光的返回发射器"""
    return arcade.Emitter(
        center_xy=prev_emitter.get_pos(),
        emit_controller=arcade.EmitBurst(3),
        particle_factory=lambda emitter: arcade.FadeParticle(
            filename_or_texture=FLASH_texture,
            change_xy=arcade.rand_in_circle((0.0, 0.0), 3.5),
            lifetime=0.15
        )
    )


def make_puff(prev_emitter):
    """返回发射器,用于生成烟花炮弹爆炸后留下的细微烟雾云"""
    return arcade.Emitter(
        center_xy=prev_emitter.get_pos(),
        emit_controller=arcade.EmitBurst(4),
        particle_factory=lambda emitter: arcade.FadeParticle(
            filename_or_texture=PUFF_texture,
            change_xy=(_Vec2(arcade.rand_in_circle((0.0, 0.0), 0.4)) + _Vec2(0.3, 0.0)).as_tuple(),
            lifetime=4.0
        )
    )


class AnimatedAlphaParticle(arcade.LifetimeParticle):
    """在三个不同的alpha级别之间设置动画的自定义粒子"""

    def __init__(
            self,
            filename_or_texture: arcade.FilenameOrTexture,
            change_xy: Vector,
            start_alpha: int = 0,
            duration1: float = 1.0,
            mid_alpha: int = 255,
            duration2: float = 1.0,
            end_alpha: int = 0,
            center_xy: Point = (0.0, 0.0),
            angle: float = 0,
            change_angle: float = 0,
            scale: float = 1.0,
            mutation_callback=None,
    ):
        super().__init__(filename_or_texture,
                         change_xy,
                         duration1 + duration2,
                         center_xy,
                         angle,
                         change_angle,
                         scale,
                         start_alpha,
                         mutation_callback)
        self.start_alpha = start_alpha
        self.in_duration = duration1
        self.mid_alpha = mid_alpha
        self.out_duration = duration2
        self.end_alpha = end_alpha

    def update(self):
        super().update()
        if self.lifetime_elapsed <= self.in_duration:
            u = self.lifetime_elapsed / self.in_duration
            self.alpha = arcade.clamp(arcade.lerp(self.start_alpha, self.mid_alpha, u), 0, 255)
        else:
            u = (self.lifetime_elapsed - self.in_duration) / self.out_duration
            self.alpha = arcade.clamp(arcade.lerp(self.mid_alpha, self.end_alpha, u), 0, 255)


class RocketEmitter(arcade.Emitter):
    """自定义发射器类,向发射器添加重力以表示烟花外壳上的重力"""

    def update(self):
        super().update()
        # 重力
        self.change_y += -0.05


class Game(arcade.Window):
    def __init__(self):
        super().__init__(SCREEN_width, SCREEN_height, '粒子焰火')

        file_path = os.path.dirname(os.path.abspath(__file__))
        os.chdir(file_path)

        arcade.set_background_color(arcade.color.BLACK)
        self.emitters = []

        self.launch_firework(0)
        arcade.schedule(self.launch_spinner, 4.0)

        stars = arcade.Emitter(
            center_xy=(0.0, 0.0),
            emit_controller=arcade.EmitMaintainCount(20),
            particle_factory=lambda emitter: AnimatedAlphaParticle(
                filename_or_texture=random.choice(STAR_textures),
                change_xy=(0.0, 0.0),
                start_alpha=0,
                duration1=random.uniform(2.0, 6.0),
                mid_alpha=128,
                duration2=random.uniform(2.0, 6.0),
                end_alpha=0,
                center_xy=arcade.rand_in_rect((0.0, 0.0), SCREEN_width, SCREEN_height)
            )
        )
        self.emitters.append(stars)

        self.cloud = arcade.Emitter(
            center_xy=(50, 500),
            change_xy=(0.15, 0),
            emit_controller=arcade.EmitMaintainCount(60),
            particle_factory=lambda emitter: AnimatedAlphaParticle(
                filename_or_texture=random.choice(CLOUD_textures),
                change_xy=(_Vec2(arcade.rand_in_circle((0.0, 0.0), 0.04)) + _Vec2(0.1, 0)).as_tuple(),
                start_alpha=0,
                duration1=random.uniform(5.0, 10.0),
                mid_alpha=255,
                duration2=random.uniform(5.0, 10.0),
                end_alpha=0,
                center_xy=arcade.rand_in_circle((0.0, 0.0), 50)
            )
        )
        self.emitters.append(self.cloud)

    def launch_firework(self, delta_time):
        launchers = (
            self.launch_random_firework,
            self.launch_ringed_firework,
            self.launch_sparkle_firework,
        )
        random.choice(launchers)(delta_time)
        pyglet.clock.schedule_once(self.launch_firework, random.uniform(1.5, 2.5))

    def launch_random_firework(self, _delta_time):
        """以随机颜色爆炸的简单烟花"""
        rocket = make_rocket(self.explode_firework)
        self.emitters.append(rocket)

    def launch_ringed_firework(self, _delta_time):
        """"具有基本爆炸和不同颜色圆环形烟花"""
        rocket = make_rocket(self.explode_ringed_firework)
        self.emitters.append(rocket)

    def launch_sparkle_firework(self, _delta_time):
        """火花闪烁的烟花"""
        rocket = make_rocket(self.explode_sparkle_firework)
        self.emitters.append(rocket)

    def launch_spinner(self, _delta_time):
        """启动喷射火花的旋转器"""
        spinner1 = make_spinner()
        spinner2 = make_spinner()
        spinner2.angle = 180
        self.emitters.append(spinner1)
        self.emitters.append(spinner2)

    def explode_firework(self, prev_emitter):
        """烟花炮弹爆炸时发生的动作,生成典型的烟花"""
        self.emitters.append(make_puff(prev_emitter))
        self.emitters.append(make_flash(prev_emitter))

        spark_texture = random.choice(SPARK_textures)
        sparks = arcade.Emitter(
            center_xy=prev_emitter.get_pos(),
            emit_controller=arcade.EmitBurst(random.randint(30, 40)),
            particle_factory=lambda emitter: arcade.FadeParticle(
                filename_or_texture=spark_texture,
                change_xy=arcade.rand_in_circle((0.0, 0.0), 9.0),
                lifetime=random.uniform(0.5, 1.2),
                mutation_callback=firework_spark_mutator
            )
        )
        self.emitters.append(sparks)

    def explode_ringed_firework(self, prev_emitter):
        """当烟花炮弹爆炸时发生的动作,产生环形烟花"""
        self.emitters.append(make_puff(prev_emitter))
        self.emitters.append(make_flash(prev_emitter))

        spark_texture, ring_texture = random.choice(SPARK_list)
        sparks = arcade.Emitter(
            center_xy=prev_emitter.get_pos(),
            emit_controller=arcade.EmitBurst(25),
            particle_factory=lambda emitter: arcade.FadeParticle(
                filename_or_texture=spark_texture,
                change_xy=arcade.rand_in_circle((0.0, 0.0), 8.0),
                lifetime=random.uniform(0.55, 0.8),
                mutation_callback=firework_spark_mutator
            )
        )
        self.emitters.append(sparks)

        ring = arcade.Emitter(
            center_xy=prev_emitter.get_pos(),
            emit_controller=arcade.EmitBurst(20),
            particle_factory=lambda emitter: arcade.FadeParticle(
                filename_or_texture=ring_texture,
                change_xy=arcade.rand_on_circle((0.0, 0.0), 5.0) + arcade.rand_in_circle((0.0, 0.0), 0.25),
                lifetime=random.uniform(1.0, 1.6),
                mutation_callback=firework_spark_mutator
            )
        )
        self.emitters.append(ring)

    def explode_sparkle_firework(self, prev_emitter):
        """烟花炮弹爆炸时发生的动作,产生闪闪发光的烟花"""
        self.emitters.append(make_puff(prev_emitter))
        self.emitters.append(make_flash(prev_emitter))

        spark_texture = random.choice(SPARK_textures)
        sparks = arcade.Emitter(
            center_xy=prev_emitter.get_pos(),
            emit_controller=arcade.EmitBurst(random.randint(30, 40)),
            particle_factory=lambda emitter: AnimatedAlphaParticle(
                filename_or_texture=spark_texture,
                change_xy=arcade.rand_in_circle((0.0, 0.0), 9.0),
                start_alpha=255,
                duration1=random.uniform(0.6, 1.0),
                mid_alpha=0,
                duration2=random.uniform(0.1, 0.2),
                end_alpha=255,
                mutation_callback=firework_spark_mutator
            )
        )
        self.emitters.append(sparks)

    def update(self, delta_time):
        # 在遍历列表时,防止列表发生变化(通常是通过回调)
        emitters_to_update = self.emitters.copy()
        # 更新云
        if self.cloud.center_x > SCREEN_width:
            self.cloud.center_x = 0
        # 更新
        for e in emitters_to_update:
            e.update()
        # 清除
        to_del = [e for e in emitters_to_update if e.can_reap()]
        for e in to_del:
            self.emitters.remove(e)

    def on_draw(self):
        self.clear()
        for e in self.emitters:
            e.draw()
        # 画距形,left, right, top, and bottom
        arcade.draw_lrtb_rectangle_filled(0, SCREEN_width, 25, 0, arcade.color.DARK_GREEN)
        mid = SCREEN_width / 2
        arcade.draw_lrtb_rectangle_filled(mid - 2, mid + 2, SPINNER_height, 10, arcade.color.DARK_BROWN)

    def on_key_press(self, key, modifiers):
        if key == arcade.key.ESCAPE:
            arcade.close_window()


def firework_spark_mutator(particle: arcade.FadeParticle):
    """所有焰火火花共享的mutation_callback"""
    # 重力
    particle.change_y += -0.03
    # drag
    particle.change_x *= 0.92
    particle.change_y *= 0.92


def rocket_smoke_mutator(particle: arcade.LifetimeParticle):
    particle.scale = arcade.lerp(0.5, 3.0, particle.lifetime_elapsed / particle.lifetime_original)


if __name__ == "__main__":
    app = Game()
    arcade.run()

  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16
  • 17
  • 18
  • 19
  • 20
  • 21
  • 22
  • 23
  • 24
  • 25
  • 26
  • 27
  • 28
  • 29
  • 30
  • 31
  • 32
  • 33
  • 34
  • 35
  • 36
  • 37
  • 38
  • 39
  • 40
  • 41
  • 42
  • 43
  • 44
  • 45
  • 46
  • 47
  • 48
  • 49
  • 50
  • 51
  • 52
  • 53
  • 54
  • 55
  • 56
  • 57
  • 58
  • 59
  • 60
  • 61
  • 62
  • 63
  • 64
  • 65
  • 66
  • 67
  • 68
  • 69
  • 70
  • 71
  • 72
  • 73
  • 74
  • 75
  • 76
  • 77
  • 78
  • 79
  • 80
  • 81
  • 82
  • 83
  • 84
  • 85
  • 86
  • 87
  • 88
  • 89
  • 90
  • 91
  • 92
  • 93
  • 94
  • 95
  • 96
  • 97
  • 98
  • 99
  • 100
  • 101
  • 102
  • 103
  • 104
  • 105
  • 106
  • 107
  • 108
  • 109
  • 110
  • 111
  • 112
  • 113
  • 114
  • 115
  • 116
  • 117
  • 118
  • 119
  • 120
  • 121
  • 122
  • 123
  • 124
  • 125
  • 126
  • 127
  • 128
  • 129
  • 130
  • 131
  • 132
  • 133
  • 134
  • 135
  • 136
  • 137
  • 138
  • 139
  • 140
  • 141
  • 142
  • 143
  • 144
  • 145
  • 146
  • 147
  • 148
  • 149
  • 150
  • 151
  • 152
  • 153
  • 154
  • 155
  • 156
  • 157
  • 158
  • 159
  • 160
  • 161
  • 162
  • 163
  • 164
  • 165
  • 166
  • 167
  • 168
  • 169
  • 170
  • 171
  • 172
  • 173
  • 174
  • 175
  • 176
  • 177
  • 178
  • 179
  • 180
  • 181
  • 182
  • 183
  • 184
  • 185
  • 186
  • 187
  • 188
  • 189
  • 190
  • 191
  • 192
  • 193
  • 194
  • 195
  • 196
  • 197
  • 198
  • 199
  • 200
  • 201
  • 202
  • 203
  • 204
  • 205
  • 206
  • 207
  • 208
  • 209
  • 210
  • 211
  • 212
  • 213
  • 214
  • 215
  • 216
  • 217
  • 218
  • 219
  • 220
  • 221
  • 222
  • 223
  • 224
  • 225
  • 226
  • 227
  • 228
  • 229
  • 230
  • 231
  • 232
  • 233
  • 234
  • 235
  • 236
  • 237
  • 238
  • 239
  • 240
  • 241
  • 242
  • 243
  • 244
  • 245
  • 246
  • 247
  • 248
  • 249
  • 250
  • 251
  • 252
  • 253
  • 254
  • 255
  • 256
  • 257
  • 258
  • 259
  • 260
  • 261
  • 262
  • 263
  • 264
  • 265
  • 266
  • 267
  • 268
  • 269
  • 270
  • 271
  • 272
  • 273
  • 274
  • 275
  • 276
  • 277
  • 278
  • 279
  • 280
  • 281
  • 282
  • 283
  • 284
  • 285
  • 286
  • 287
  • 288
  • 289
  • 290
  • 291
  • 292
  • 293
  • 294
  • 295
  • 296
  • 297
  • 298
  • 299
  • 300
  • 301
  • 302
  • 303
  • 304
  • 305
  • 306
  • 307
  • 308
  • 309
  • 310
  • 311
  • 312
  • 313
  • 314
  • 315
  • 316
  • 317
  • 318
  • 319
  • 320
  • 321
  • 322
  • 323
  • 324
  • 325
  • 326
  • 327
  • 328
  • 329
  • 330
  • 331
  • 332
  • 333
  • 334
  • 335
  • 336
  • 337
  • 338
  • 339
  • 340
  • 341
  • 342
  • 343
  • 344
  • 345
  • 346
  • 347
  • 348
  • 349
  • 350
  • 351
  • 352
  • 353
  • 354
  • 355
  • 356

源码获取

关注博主后,私聊博主免费获取
需要技术指导,育娃新思考,企业软件合作等更多服务请联系博主

今天是以此模板持续更新此育儿专栏的第 33/50次。
可以关注我,点赞我、评论我、收藏我啦。

声明:本文内容由网友自发贡献,不代表【wpsshop博客】立场,版权归原作者所有,本站不承担相应法律责任。如您发现有侵权的内容,请联系我们。转载请注明出处:https://www.wpsshop.cn/w/IT小白/article/detail/682037
推荐阅读
相关标签
  

闽ICP备14008679号