使用win2d实现萤火虫粒子效果

这几天我在做游戏的标题画面,需要实现随机飞舞的萤火虫。萤火虫会闪烁黄绿色的光,远近不同,并且飞出屏幕边界不久会自动飞回来。

我前一阵子用win2d写了个简单的游戏引擎(现在还是alpha阶段),用它可以减少代码量。

https://github.com/Nukepayload2/Nukepayload2.Graphics.N2Engine

那么,大概设计一下。

萤火虫用粒子系统实现比较方便,所以Models有两个类,一个是FireflyParticle,另一个是FireflyParticleSystem。

游戏标题画面有一个ViewModel。

萤火虫呈现类是FireflyParticleSystemView,自定义的游戏视图一个类。所以有2个Views的类

资源文件夹里面要添加xxxResourceManager,尽管这次我们不用任何图片素材。

开始代码。首先拿FireflyParticle开刀。

Public Class FireflyParticle
    Inherits Particle

    Public Property Radius As Single
    Public Property CenterColor As Color
    Public Property Opacity As Single = 1
    Public Property Parent As FireFlyParticleSystem
    Public Sub New(acceleration As Vector2, lifeTime As Integer, location As Vector2, velocity As Vector2, radius As Single, centerColor As Color, parent As FireFlyParticleSystem)
        MyBase.New(acceleration, lifeTime, location, velocity)
        Me.Radius = radius
        Me.Parent = parent
        Me.CenterColor = centerColor
        delta = 0.3 + 0.12 * Rndf()
    End Sub

    Dim delta!

    Public Overrides Sub Update()
        MyBase.Update()
        Opacity -= delta!
        Dim ub = Math.Max(0, 1 - Age / LifeTime)
        If Opacity < 0 OrElse Opacity > ub Then
            delta = -delta
            If Opacity < 0 Then
                Opacity = 0
            ElseIf Opacity > ub Then
                Opacity = ub
            End If
        End If
        Radius -= Radius / LifeTime
        Velocity += New Vector2(Rndf() - 0.5, Rndf() - 0.5).WithLength(0.5)
        Const bound = 20
        Dim lx = Location.X, ly = Location.Y, vx = Velocity.X, vy = Velocity.Y
        If lx < -bound Then
            lx = -bound
            vx = -vx
        ElseIf lx - bound > Parent.Width Then
            lx = Parent.Width + bound
            vx = -vx
        End If
        If ly < -bound Then
            ly = -bound
            vy = -vy
        ElseIf ly - bound > Parent.Height Then
            ly = Parent.Height + bound
            vy = -vy
        End If
        Location = New Vector2(lx, ly)
        Velocity = New Vector2(vx, vy).WithLength(Parent.MaxSpeed)
    End Sub
End Class

FireflyParticle类实现的是单独的萤火虫的飞舞,闪烁产生的数据变动。大多数的变量名很规范,所以不多解释了。

接下来的是粒子系统。实现了自适应窗口大小的一半功能,还关联了一个呈现用的类(这里为了利用Intellisense的自动创建类代码的功能减少工作量才这样设计,粒子系统类不访问呈现类的任何成员)。

Public Class FireFlyParticleSystem
    Inherits ParticleSystem(Of FireflyParticle)

    Public Sub New(spawnInterval As Integer, initialCount As Integer, width As Integer, height As Integer, baseColor As Color)
        Me.InitialCount = initialCount
        Me.SpawnInterval = spawnInterval
        Me.Width = width
        Me.Height = height
        Me.BaseColor = baseColor
        For i = 0 To initialCount - 1
            Dim part = CreateParticle()
            part.Age = part.LifeTime - i / initialCount * part.LifeTime
            Particles.Enqueue(part)
        Next
    End Sub
    Protected Overrides Sub OnParticleRemoved()
        MyBase.OnParticleRemoved()
        Particles.Enqueue(CreateParticle())
    End Sub
    Public Overrides Property Particles As New Queue(Of FireflyParticle)
    Public Overrides ReadOnly Property Presenter As GameVisualView = New FireFlyParticleSystemView(Me)
    Public Overrides Property SpawnCount As Integer = 1
    Public Overrides Property SpawnDuration As Integer = Integer.MaxValue
    Public Property InitialCount As Integer
    Public Overrides Property SpawnInterval As Integer = Integer.MaxValue
    Public Property Width As Integer
    Public Property Height As Integer
    Public Property BaseColor As Color
    Public Property MaxSpeed As Double = 1.4
    Protected Overrides Function CreateParticle() As FireflyParticle
        Return New FireflyParticle(New Vector2, (SpawnInterval * (0.6 + 0.4 * Rndf())), New Vector2(Rndf() * Width, Height * Rndf()), New Vector2(Rndf() - 0.5, Rndf() - 0.5).WithLength(MaxSpeed), 5 + Rndf(), BaseColor, Me)
    End Function
End Class

下面是ViewModel。向AnimObjects集合绑定了上面的萤火虫粒子系统,并且通过事件更新粒子系统的宽度和高度(绑定方式略原始,我正考虑怎样改进这个过程)。

Public Class ImTheBossTitleScreenN2ViewModel
    Inherits GamePanel

    Public Sub New(SpaceSize As Size)
        MyBase.New(SpaceSize)
    End Sub

    Dim FireflySys As FireFlyParticleSystem
    Protected Overrides Sub InitializeGameVisuals()
        FireflySys = New FireFlyParticleSystem(10000, 20, SpaceSize.Width, SpaceSize.Height, Colors.YellowGreen)
        AnimObjects.Add(FireflySys)
    End Sub

    Private Sub ImTheBossTitleScreenN2ViewModel_SizeChanged(NewSize As Size) Handles Me.SizeChanged
        FireflySys.Width = NewSize.Width
        FireflySys.Height = NewSize.Height
    End Sub
End Class

View代码只发呈现萤火虫。

萤火虫的光可以用对实心圆进行扩大组织变换再进行高斯模糊模拟。

Friend Class FireFlyParticleSystemView
    Inherits TypedGameVisualPresenter(Of FireFlyParticleSystem)

    Public Sub New(Target As FireFlyParticleSystem)
        MyBase.New(Target)
    End Sub

    Public Overrides Sub OnDraw(sender As GamePanelView, DrawingSession As CanvasDrawingSession, Canvas As ICanvasResourceCreator)
        For Each fireFly In Target.Particles
            Using cl As New CanvasCommandList(DrawingSession), ds = cl.CreateDrawingSession
                Using glow As New GlowEffectGraph
                    Dim color = fireFly.CenterColor
                    color.A = CByte(fireFly.Opacity * 255)
                    ds.FillCircle(fireFly.Location + Target.Location, fireFly.Radius, color)
                    glow.Setup(cl, fireFly.Radius)
                    DrawingSession.DrawImage(glow.Output)
                End Using
            End Using
        Next
    End Sub

    Public Overrides Sub OnGlobalQualityChanged(Quality As GraphicQualityManager)

    End Sub
End Class

Class GlowEffectGraph
    Implements IDisposable

    Public ReadOnly Property Output() As ICanvasImage
        Get
            Return blur
        End Get
    End Property

    Private morphology As New MorphologyEffect() With {
        .Mode = MorphologyEffectMode.Dilate,
        .Width = 1,
        .Height = 1
    }

    Private blur As New GaussianBlurEffect() With {
        .BlurAmount = 0,
        .BorderMode = EffectBorderMode.Soft
    }

    Public Sub New()
        blur.Source = morphology
    End Sub

    Public Sub Setup(source As ICanvasImage, amount As Single)
        morphology.Source = source
        Dim halfAmount = Math.Min(amount / 2, 100)
        morphology.Width = CInt(Math.Truncate(Math.Ceiling(halfAmount)))
        morphology.Height = CInt(Math.Truncate(Math.Ceiling(halfAmount)))
        blur.BlurAmount = halfAmount
    End Sub

#Region "IDisposable Support"
    Private disposedValue As Boolean ‘ 要检测冗余调用

    ‘ IDisposable
    Protected Overridable Sub Dispose(disposing As Boolean)
        If Not disposedValue Then
            If disposing Then
                ‘ TODO: 释放托管状态(托管对象)。
                Output?.Dispose()
                morphology.Dispose()
                blur.Dispose()
            End If

            ‘ TODO: 释放未托管资源(未托管对象)并在以下内容中替代 Finalize()。
            ‘ TODO: 将大型字段设置为 null。
        End If
        disposedValue = True
    End Sub

    ‘ TODO: 仅当以上 Dispose(disposing As Boolean)拥有用于释放未托管资源的代码时才替代 Finalize()。
    ‘Protected Overrides Sub Finalize()
    ‘    ‘ 请勿更改此代码。将清理代码放入以上 Dispose(disposing As Boolean)中。
    ‘    Dispose(False)
    ‘    MyBase.Finalize()
    ‘End Sub

    ‘ Visual Basic 添加此代码以正确实现可释放模式。
    Public Sub Dispose() Implements IDisposable.Dispose
        ‘ 请勿更改此代码。将清理代码放入以上 Dispose(disposing As Boolean)中。
        Dispose(True)
        ‘ TODO: 如果在以上内容中替代了 Finalize(),则取消注释以下行。
        ‘ GC.SuppressFinalize(Me)
    End Sub
#End Region
End Class

这里我纠正了win2d gallery示例代码的错误:GlowEffectGraph类最好实现IDisposable,这样可以避免内存释放不及时带来应用闪退,或者产生性能问题。

效果图(注意看那些绿色光斑):

效果视频:

http://v.youku.com/v_show/id_XMTU3MzA1ODg3Ng==.html

时间: 2024-12-07 17:10:24

使用win2d实现萤火虫粒子效果的相关文章

优化win2d实现的萤火虫粒子效果

前几天我发了个技术博客,告诉大家怎样用Win2D 画萤火虫动画 . 那种绘制萤火虫的方式虽然画质高,但是性能不好,萤火虫数量超过50就可以感受到帧数下降. 我今天想到了一种牺牲画质提升性能的绘制方式,就算是画520只闪烁并且不远离画布的萤火虫都不会掉帧. 优化思路如下: 原本绘制萤火虫的代码是这样的: Public Overrides Sub OnDraw(sender As GamePanelView, DrawingSession As CanvasDrawingSession, Canva

cocos基础教程(8)粒子效果

简介 粒子系统是指计算机图形学中模拟特定现象的技术,它在模仿自然现象.物理现象及空间扭曲上具备得天独厚的优势,为我们实现一些真实自然而又带有随机性的特效(如爆炸.烟花.水流)提供了方便. 粒子属性 一个强大的粒子系统它必然具备了多种多样的属性,这样才能配置出多样的粒子.下面就来看看粒子系统的主要属性吧. 主要属性: _duration 发射器生存时间,即它可以发射粒子的时间,注意这个时间和粒子生存时间不同.单位秒,-1表示永远:粒子发射结束后可点击工具栏的播放按钮再次发射 _emissionRa

关于Unity中粒子效果的使用

粒子效果1: 游戏中会有很炫酷的特效,比如爆炸,水花,火焰等;2: unity提供粒子编辑器,方便特效人员来开发很炫酷的特效;3.粒子效果一般有专门的粒子特效师来做,我们只需要拿来用就好了,很多参数没必要掌握. Particle System组件面板 1: 粒子系统主体;2: 喷射(Emission);3: 形态(shape);4: 生命周期内的速度偏移(velocity over lifetime);5: 生命周期内的限制速度(limit velocity over lifetime);6:

IOS开发——UI进阶篇(十八)核心动画小例子,转盘(裁剪图片、自定义按钮、旋转)图片折叠、音量震动条、倒影、粒子效果

一.转盘(裁剪图片.自定义按钮.旋转) 1.裁剪图片 将一张大图片裁剪为多张 // CGImageCreateWithImageInRect:用来裁剪图片 // image:需要裁剪的图片 // rect:裁剪图片的尺寸,传递是像素 CGImageRef norImage = CGImageCreateWithImageInRect(norBigImage.CGImage, clipRect); 2.每次点击按钮立马变为选中状态,并且取消上次的按钮的选中状态 当然还要重写- (void)setH

libgdx 2D 粒子效果二

在上一篇随笔中,我们能够把粒子效果在stage中使用了. 想了想,在实际应用中粒子效果可能有2中使用的情况: 1. 单独的粒子效果,比如一个飞行的火球.他跟真正的Actor没啥关系,只有自己的position或者说飞行轨迹. 施法者放完后爱哪玩去哪玩去,粒子效果跟他无关了. 2. 跟真正的Actor相关的粒子效果,比如飞机发动机的火焰,或者飞机爆炸的效果. 他一直跟着飞机在动. -------------------当然以上两种未必用粒子效果实现,我只是这么说... 对于第二种情况,不防封装一个

超炫的粒子效果!代码,就应该这么写!

最近瞎逛的时候发现了一个超炫的粒子进度效果,有多炫呢?请擦亮眼镜! 粗略一看真的被惊艳到了,而且很实用啊有木有!这是 Jack Rugile 写的一个小效果,源码当然是有的.聪慧如你,肯定觉得这个东西so easy 要看啥源码,给我3分钟我就写出来了吧.所以你的思路可能是: 1)进度条的实现没什么好说的,简单的一个 fillRect(0,0,long,20),long和20是分别进度条的长宽.然后每帧动画调用前将画布清除clearRect(0,0,canvas.width,canvas.heig

C#学习日志 day9 -------------- cocos2d-x 3.0 粒子效果简介

cocos2d是一款实用的游戏引擎,其可以在windows phone中应用,但是比较差强人意的是其代码只能用c++来写. 因为我们的wp应用我负责粒子效果的实现,所以这里我介绍一下各种粒子效果. cocos2d中自带了十种粒子效果.可以说,一般的效果我们都可以用cocos2d自带的粒子效果实现.即使不能我们也可以通过对其自带粒子效果进行一些属性的调整从而实现我们想要的效果. 这里先贴出十种粒子效果的实现代码 ParticleRain *snow = ParticleRain::create()

Canvas + JavaScript 制作图片粒子效果

首先看一下源图和转换成粒子效果的对比图:       左侧图片为源图,右侧图片为粒子效果图.该效果是在Canvas画布上制作的.将图片制作成粒子效果相对而言是比较简单的.重点了解两个知识点即可 1:图片是通过image对象形式绘制在画布上的,然后使用Canvas的getImageData接口,获取图像的像素信息. var imageData=ctx.getImageData(x, y, width, height); 参数说明:x,y为画布上的x和y坐标 width,height为获取指定区域图

用仿ActionScript的语法来编写html5——第八篇,图片处理+粒子效果

用仿ActionScript的语法来编写html5系列开发到现在,应该可以做出一些东西了,下面先来研究下图片的各种效果预览各种效果看下图 效果和代码看这里,看不到效果的请下载支持html5的浏览器 http://fsanguo.comoj.com/html5/jstoas07/index.html 2013年3月13日追加 该系列文章写的很早,目前该系列文章中所总结的方法等都已经封装进了lufylegend.js引擎里 lufylegend.js引擎的下载链接 http://lufylegend