欢迎阅读 弹幕引擎 / 弹幕会模板 使用教学!
不知道您是否听说过“弹幕游戏”,Scratch 闯关游戏作品:东方虹魔馆
如果听说过,那就太好啦!您很有可能已经对“弹幕”甚至“符卡”有了认识基础。没有也不要紧,您可以观看下面这个视频,来大致感受一下“弹幕可以是什么样子的”:
弹幕引擎使用教学
弹幕新约隐藏符卡
飞镖,小球,包括激光,视频中的玩家正在努力躲避的那些东西,共同构成了一副不明觉厉的画面——它们都是“弹幕”
东方的招牌,除了性格各异的可爱少女们,不可不提它五花八门的弹幕——可不要觉得“东方”就是指代超密无解弹幕哦!
截图组成的奇怪阵营图
异彩纷呈的攻击,千人千面的表达,紧张刺激、而又充满独特美感的游戏体验,就是笔者对“东方风弹幕”整体印象的概括。
我非常喜欢的符卡
弹幕会模板,相当于一个功能相当完善的东方风弹幕STG引擎,让玩家免于搭建底层的辛苦,能够将大多数精力放在设计本身。
但是,自从Simple前辈接手了模板制作,伴随着模板功能的超级提升,上手难度也确实有所增加。
代码逻辑而言:专门为STG系统设计的脚本乃至角色分工,逻辑会有些陌生,需要结合案例来了解学习;
代码习惯而言:大量纯英文命名的变量、自定义方法,乃至STG黑话,可能会对部分SCer造成阅读障碍;
本文将会介绍弹幕的基本运行逻辑、第五届弹幕会模板的基本使用方法,顺带分享一些笔者的弹幕设计经验。希望能对您参与弹幕会活动,乃至独立制作弹幕游戏有所帮助!
将配合弹幕会模板进行对照讲解
“最初与最后的无名弹幕”
本部分内容:
“子弹是什么?”:弹幕的基本功能与脚本实现;脚本之间的关系
“我要怎么做?”:初步了解“如何制作弹幕”
“为什么要这么做?”:初步了解“东方风弹幕设计理念”
使用弹幕会模板的好处
这些内容将会相互穿插,编排尽可能遵循认识发展规律。
需要您基本了解Scratch中的克隆体、公有 / 私有变量的性质,
弹幕是许多子弹构成的。
所以,我们以一个基础问题引入:子弹是什么,需要做什么呢?
子弹是对玩家有威胁的飞行物
它会重复出现,所以是克隆体。
它会从某个地方出发,会飞会动,碰到边界或者玩家都会消失——就像常识里的那样。
据此,我们容易写出这样的程序:
挺轻松的呢,【克隆(自己)】孤零零的真可怜。
可是,你会在模板程序页的Danmaku角色中,看到这样的景象:
它们很美,不是吗?但内容多到超乎想象。
这么多?不要怕!先随我的脚步,概括一下上图两列脚本的内容:
宛如语文题中的“缩句”
这里有些“弹幕STG的黑话”,比如那各出现两次的Spellcard和Danmaku,容易让人不明所以,我们慢慢介绍。
——左边那条先不讲,所以先单把右面那一列拎出来。
因为Danmaku,日语“弹幕”的罗马音,也是弹幕会的名字来源。
这里Danmaku要表达的意思,其实和汉语游戏语境下的“子弹”一样。
所以,这小不点一个,其实就是子弹总程序了
最初那个“子弹脚本”和模板中的这个“乍一看比较迷糊的子弹程序”,在结构上,其实几乎一致。
我们接下来会大量地使用“类比”的学习方法!
Danmaku Init,即子弹初始化;
Run Danmaku,即子弹运行;
delete data,即删除子弹数据;
delete anime,即子弹消失前的动画;也属于子弹删除的一部分。
完成度极高的模板和几十秒搭出来的程序,结构是“一样的”?
按照执行顺序划分,总是可以将子弹的生命流程概括为四个段落。
(被)生成
初始化
运行
删除(本文不会在它身上费太多时间)
那为什么没简化之前的脚本这么复杂?
解释起来其实简单:
“弹幕游戏”之所以叫弹幕游戏,是因为它把大量的设计内容放在弹幕的运作上。如这一部分开头所说的:“弹幕”实际上就是由许多子弹组成的。所以,为了实现各种各样的子弹功能,直接相关弹幕的底层代码就变得十分丰富。
不过,大道归简:
“生成”、“初始化”、“运行”三者,正是弹幕设计中最为核心的部分。
不过,您注意到了吗?图片中并没有注出“生成”,只提到“初始化”和“运行”呢。
——正如刚才暗示的:子弹是“被生成”的!
那么,是谁在生成子弹呢?
您很容易想到这是“本体”做的,而且三下五除二就能搞出一个转着射的弹幕出来,用行动说明您明白。
到此为止,您其实已经组织完“一个弹幕”所需的所有功能部分了!
虽然长得不霸气,但是,上图的脚本,无疑正是起到“生成子弹”的重要功能的脚本!
实际上在弹幕会模板中也是一样的。只不过盖了一层自定义积木,看起来并不那么“暴露”:
上图中:
Run Spellcard,即符卡运行状况。该值为1时,表明有符卡正在运行,否则没有。
Spellcard Main,即符卡运行。
其他部分(比如danmaku i/j/k),我们暂先略过。
Spellcard,也就是“符卡”!
那个粉色的,被醒目标注出来的“Spellcard Main”中,蕴藏着一堆的“生成子弹”脚本。
我们找到Spellcard Main的本体一看……
“超纲知识”?
哎呀,这就直探核心科技,很多属于第二部分的内容了。
我们可以暂先歇脚,搞点活,比如让子弹做个漂亮的回旋,
——不过,旋转角度填太大的话,子弹就飞不出去了。
您可以调调参数,实验一下合适的速度/角速度组合!
这一步添加,丰富的正是“子弹运行”的部分!
虽说,就是一个积木一个数的事呢,但确实让子弹完成了个不同于直飞的小小演出。
不过——只是到此为止的话……您可能偶尔会遇到事故:
怎么回事!
浅层的病因:Scratch无法让环境稳在一个确定的运行帧率上(也就是常说的“fps”不稳定),导致 “等待0.2秒”(使用蓝色计时器也是一个道理)放在程序里,其实是个“不稳定的定时炸弹”——或许它对于您来说是0.2秒,但对于活在一次次执行中的子弹们来说,“0.2秒”就是一个忽远忽近的距离,这将损坏弹幕的形状——此乃对美对秩序的毁灭性打击呀!
庆幸的是,我们有一种方法来解决这种问题——那就是,依赖一个更可靠的“变量计时器(timer,简称t)”:
程序内的运动并不像现实一样看起来连续,而是有着明确的时间单位——它叫做“帧”。在通常的Scratch运行环境下,1秒=30帧。
我们把计时的根据从现实(比如0.2秒)挪到程序内(比如15帧),让它和程序的其他部分统一,这样子,您的设备就算是卡顿,计时器也会老老实实地等着。等程序运作起来了,它才会一个一个往上加数。
程序里会有很多个相互独立的计时器。
但怎么把计时器和弹幕发射缝在一起呢?
常识地来,从0开始数,数到5就打一发!然后再从0开始,……
这是不错的思路!凭此,您可以写出类似这样的程序:
出于方便对接的目的,这里将变量名与模板统一;Spellcard t,即“Spellcard的计时器”
你会看到,Spellcard t变量的显示数值在飞快地循环变化:0,1,2,3,4,0,1,2,3,4,……
弹幕连成的链条(chain)也旋转起来,就像扇叶一样。不停不停地转。
我们先不着急推进度:重新审下题,把目标概括成“每五帧发射一次”的话,您有没有想到其它的实现思路呢?
提示:需要用到某个数学运算!
求余运算!这东西原理简单,但十分有用!
经过这一步运算处理,[timer 除以 5 的余数]也会飞快地循环变化:0,1,2,3,4,0,1,2,3,4,……
表面上都是“0,1,2,3,4,……”循环,难道是说,这两种方法可以随便用,互相替换吗?
我们先从原理上比较这两种方法的不同!
出于方便,暂时把前面那种称为“赋值处理”,后面那种称为“运算处理”。
赋值处理:Spellcard t本身受到影响。
运算处理:Spellcard t本身不受影响。
我先卖个关子,由你思考“运算处理”在复杂情况(同时存在多种弹幕生成脚本)下的长处!
“两种弹幕”?
没错!赋值处理会覆盖掉计时器的内容,从而导致各种弹幕的生成(发射)时间受到波及。
你知道吗?一个符卡可以包含许多种不同的弹幕,这在弹幕设计中是相当常见的。
运算处理就不会导致这种“波及”——它只把数据拿来算一下,各判断各的,就把它原样交回去了。
从另一个角度说:所有的弹幕生成程序,其实都是一条绳子(同一个计时器)上的蚂蚱。所以,调用计时器并进行运算一般不会造成任何问题,但对计时器赋值就需要谨慎。
我们先采取激进策略,把计时器推广开——改造子弹的程序,让它也随时间做点演出!
改进版的子弹程序!
良好的代码习惯,包括良好的变量命名习惯!
你注意到了吗?在模板中,大写字母开头的变量(比如Spellcard t)都是公有的,而小写字母开头的变量(比如danmaku t)都是私有的。
现在,所有的子弹都会在“0到100帧期间”(换算成秒则是“0到100/30秒期间”)既移动、又旋转,而在之后的时间里,只会移动,不再旋转。
反正是不怕角速度(指 [左转( )度] 的括号中填入的数字)写大了!
而且既然提到了多种弹幕的生成,怎么能不提到多种弹幕的运行
可不能让一套方法定死了所有的子弹!
都是克隆体,怎么才能让一些子弹执行这些程序,一些子弹执行那些程序呢?
区分子弹执行的脚本,首先需要区分子弹——比如,借助变量“种类(type)”
以此为判断依据,脚本就能方便地“区别对待”各种子弹了——不错!
但再在此之前,还得生成“type不同的子弹”:
生成的部分也来个照应
理论已经基本完备了,我们火急火燎地提出一个实践问题:
希望第一种弹幕只在前50帧发射,每5帧发射一次,子弹先旋转100帧、后直飞……
——打住!如果想要让弹幕的时间安排得更具体,往往需要配合“另一种时间约束方法”。你可以猜一猜,所谓的“另一种约束方法”是指什么:
其实就是简单地约束t的范围!
第二种弹幕则是每15帧发射一次,加速100帧后直飞。
综合这两种需求,该怎么写呢?
上图中的内容,您能完全理解吗?
我们再对照模板,看一看结构的相似之处!
模板中的各种“标志”;不要忘记小写打头变量都是私有变量!
图中的部分内容将在第二部分讲解,当然我们更鼓励通过观察实践自主学习。
如您所见:模板中的Spellcard与Danmaku脚本,其实也有这样具体而密切的关联!
三层约束,确保每种弹幕都是随意愿而动。
“发射-初始化-运行”,围绕某种弹幕,环环相扣地设置,正是弹幕编写的“单位操作”。而在弹幕会模板中,这部分脚本顺次放置。
我们再看一眼最初的逻辑——图中的内容,是否已经变明晰了呢?
“至此,弹幕的基本逻辑已经介绍完毕了!”
笔者相信,经您对上述内容的大致理解,
您能够基本了解弹幕脚本的分工,以及它们强烈明确的关联,以保证使用模板制作弹幕时不会迷失方向;但您也应该知道,这只是弹幕底层的冰山一角。
您也可以摸索出应该如何自主设计时间约束条件。而在第二部分,本文将继续围绕“t”,介绍它的其它应用和模板的强大功能;在第三部分,您将了解到“时间(节奏)设计也是弹幕美感设计的重要内容”。
希望这一部分内容,能够对您使用弹幕会模板进行(最重要的那一部分)弹幕制作起到帮助作用!
突然留下了一点可读可不读的思考问题:
如果不使用变量计时器(当然,更不能用Scratch自带的计时器),能否做出“子弹在射出后的前2秒,都是边转边走,2秒之后,变成直飞”的效果?
“等待?”——不行哦,等待会直接截停这一脚本,子弹连动都动不了了^^|||
“那再补一个‘当作为克隆体启动时’?”——难道要每种这样的弹幕都要另开好几行?不具普适性呢。
“那就不搞这么麻烦!”——想偷懒?我们有需求,必须解决问题!
我们可以将上述问题一般化为:
“如何让子弹的各种变化(包括移动)放在同一个积木(“当作为克隆体启动”)之下,而在执行时间上又不相互波及?”
这个问法,你是否觉得似曾相识呢?
没错,它和前述“弹幕生成”中的复杂情况是本质相同的!
解决方法也可以粗略地复述为:
不用等待X秒,而用t(danmaku t)相关的运算和判断!
若要深入说明,则必然要涉及到“线程”的概念,碍于笔者专业性不足,无法将原理以通俗的语言道出,以及,本文主要内容并非讲解编程知识,故不在此展开太多了。
另外,不知道您阅读至今,是否有这个疑惑:为什么子弹非要转这个角、加这个速不可?
笔者的措辞无非是“漂亮的”“演出”,确实比干动能丰富多彩点……那子弹为什么要表演?
弹幕不但能对玩家造成威胁,而且能够描绘“美”。
较于任何其它STG,在关于“子弹应该做什么”这一点的认识上,东方风STG有着它鲜明的主张——那就是,弹幕“应当”表现美。这个主张,或者说“东方风弹幕设计理念”,也决定了在东方风STG的框架下,除了玩法设计,还会有一份格外的重磅的用心——那正是“弹幕的美观设计”。
在第三部分,笔者将会着重说明这部分内容。
愿工具能够帮助呈现你的创意:
弹幕样例的分析
模板内的统一命名
便捷的弹幕发射积木
便捷的Boss操控积木
简单的符卡循环
如何自学
弹幕的运动与形状的,具体玩法和审美体验
获得弹设灵感的渠道
装饰弹幕设计
实用弹幕设计
弹幕设计的时间和空间