为什么标题是 #3 而不是 #2 ?

——因为 #2 还在咕咕中。


要实现的效果大概如下动图所示。

(Source: LeaF - Doppelganger)

Coding

定义

先实现一个简单的,1 -> 4 -> 16 -> $4^n$ 的分裂。

首先想想这个方法该怎么定义?

接受一组的精灵图,分割次数、时间以及间隔。
还得有个对每个元素进行变换的方法。

所以:

void Devide(Dictionary<string, OsbSprite> sprites, int step, int startTime, int duration, Func<DevideParam, OsbSprite> func)

考虑到需要用 ID 区分每种精灵图,我使用了 Dictionary 作为输入。

实现

由我们的小学数学知识可知,第 $n$ 次会分裂成 $4^{n-1}$ 个画面。
不过这个数字好像没有什么用。

那么通过数数易知,第 $n$ 次分裂时行数列数均为 $2^{n-1}$ 。

所以我们先搞一个三重循环看看:

for (int i = 0; i < step; ++i)
{
    var npl = (int)Math.Pow(2, i);

    for (var j = 0; i < npl; ++j)
    {
        for (var k = 0; k < npl; ++k) 
        {
            //...
        }
    }
}

WIP…


效果

8TRpsf.gif

每张精灵图大小必须小于 854 * 480 ,否则会重叠在一起。

Source

using OpenTK;
using OpenTK.Graphics;
using StorybrewCommon.Mapset;
using StorybrewCommon.Scripting;
using StorybrewCommon.Storyboarding;
using StorybrewCommon.Storyboarding.Util;
using StorybrewCommon.Subtitles;
using StorybrewCommon.Util;
using System;
using System.Collections.Generic;
using System.Linq;

namespace StorybrewScripts
{
    public class Test : StoryboardObjectGenerator
    {
        public override void Generate()
        {
            var d = new Dictionary<string, OsbSprite>() {
                {"c", GetLayer("c").CreateSprite("sb/arrow.png")},
                {"b", GetLayer("").CreateSprite("sb/linelineline.png")}
            };

            Devide(d, 4, 1095, 300, (p) => {
                switch (p.Id) {
                    case "c":
                        p.Sprite.Rotate((double)p.Time, (double)(p.Time + 300), 0, 1);
                        break;
                }
            });

        }

        public class DevideParam {
            public string Id;
            public OsbSprite Sprite;
            public double Time;
        }

        public void Devide(Dictionary<string, OsbSprite> sprites, int step, int startTime, int duration, Func<DevideParam, OsbSprite> func) 
        {
            for (int i = 0; i < step; ++i) {
                var npl = (int)Math.Pow(2, i);

                var xd = 854f / npl;
                var yd = 480f / npl;

                foreach (var item in sprites)
                {
                    using (var pool = new OsbSpritePool(GetLayer(item.Key), item.Value.TexturePath, OsbOrigin.Centre, (sprite, st, et) => {

                        sprite.Fade(st, 1);
                        sprite.Fade(et, 0);

                        func.Invoke(new DevideParam{
                            Id = item.Key,
                            Sprite = sprite,
                            Time = st,
                        });
                    }))
                    {
                        for (int j = 0; j < npl; ++j) 
                        {
                            for (int k = 0; k < npl; ++k) 
                            {
                                var s = pool.Get(startTime + i * duration, startTime + (i + 1) * duration);
                                var newvec = new Vector2(xd * j - 107 + (item.Value.InitialPosition.X + 107) * (1.0f / npl), yd * k + item.Value.InitialPosition.Y * (1.0f / npl));

                                s.Move(startTime + i * duration, newvec);
                                s.Scale(startTime + i * duration, 1.0f / npl);
                            }
                        }
                    }
                }
            }
        }
    }
}

o!sb stuff      storyboard o!sb

本博客所有文章除特别声明外,均采用 CC BY-SA 3.0协议 。转载请注明出处!