175 6191 5976

添加官方微信

领创时代关于网站建设、青岛画册设计、青岛网站设计的观点和相关新闻 将我们的想法与焦点与你共享

一文看懂如何将Flash游戏转换为HTML5

2019-06-06 来源:小领

Adobe正在慢慢放弃Flash,转而使用HTML5和JavaScript; 它的官方报废定在2020年。这就是本文将派上用场的地方。下面介绍的技巧旨在帮助HTML5游戏开发人员在将Flash游戏转换为JavaScript时避免常见错误,并使整个开发过程尽可能顺利进行。您所需要的只是JavaScript,WebGL和Phaser框架的基本知识。

将游戏设计从SWF更改为JavaScript可以产生更好的用户体验,从而使其具有现代外观。但怎么办呢?你需要一个专门的JavaScript游戏转换器来摆脱这种过时的技术吗?好吧,Flash到HTML5的转换可能是件小事 - 这就是有经验的JavaScript游戏开发者对此事所说的话。 

改善HTML5游戏体验。将游戏转换为另一个平台是改善它,解决问题和增加受众的绝佳机会。以下是一些可以轻松完成并且值得考虑的事情:

从Flash转换为JavaScript允许覆盖更广泛的受众 - 移动设备用户通常需要在游戏中实现对触摸屏控件的支持。幸运的是,Android和iOS设备现在也支持WebGL,因此通常可以轻松实现30或60 FPS渲染。在许多情况下,60 FPS不会导致任何问题,只会随着时间的推移而改善,因为移动设备的性能越来越高。在比较ActionScript和JavaScript时,后者更快。除此之外,转换游戏是重新审视游戏代码中使用的算法的好机会。使用JavaScript游戏开发,您可以优化它们或完全删除原始开发人员留下的未使用的代码。
让新开发人员查看游戏的源代码可以帮助修复已知的错误或发现新的和非常罕见的错误。这样可以减少玩家对游戏的刺激,这会让他们花更多的时间在你的网站上,并鼓励他们尝试你的其他游戏。除了跟踪流量之外,网络分析还可用于收集有关玩家在游戏中的行为方式以及在游戏过程中遇到困难的知识。添加本地化这会增加观众,对于来自其他国家/地区的孩子来说非常重要。或者你的游戏可能不是英文,你想支持那种语言?

达到60 FPS。谈到JavaScript游戏开发,可能很有可能将HTML和CSS用于游戏内按钮,小部件和其他GUI元素。我们的建议是在这里小心。这是违反直觉的,但实际上利用DOM元素在复杂游戏中的表现较差,这在移动设备上具有更大的意义。如果要在所有平台上实现恒定的60 FPS,则可能需要从HTML和CSS重新签名。

通过使用常规图像(“Phaser.Image”类),利用“.crop”属性进行修剪和“Phaser”,可以在Phaser中轻松实现非交互式GUI元素,例如健康条,弹药条或计分计数器。文本'简单文本标签类。

可以使用内置的“Phaser.Button”类来实现按钮和复选框等交互式元素。其他更复杂的元素可以由不同的简单类型组成,例如组,图像,按钮和文本标签。

加载自定义字体
如果要使用自定义矢量字体(例如TTF或OTF)渲染文本,则需要确保在渲染任何文本之前浏览器已经加载了该字体。Phaser v2.6没有为此提供解决方案,但可以使用另一个库 - Web Font Loader。

假设您有一个字体文件并在页面中包含Web Font Loader,那么下面是一个如何加载字体的简单示例。创建一个将由Web Font Loader加载的简单CSS文件(您不需要将其包含在HTML中):

@font-face {
  // This name you will use in JS
  font-family: 'Gunplay';
  // URL to the font file, can be relative or absolute
  src: url('../fonts/gunplay.ttf') format('truetype');
  font-weight: 400;
}
现在定义一个名为WebFontConfig的全局变量。像这样简单的东西通常就足够了:

var WebFontConfig = {
  'classes': false,
  'timeout': 0,
  'active': function() {
  // The font has successfully loaded...
  },
  'custom': {
  'families': ['Gunplay'],
  // URL to the previously mentioned CSS
  'urls': ['styles/fonts.css']
  }
};
请记住将代码放在上面显示的“活动”回调中。就是这样!

现在我们处于Flash to JavaScript转换的中间位置 - 是时候处理着色器了。要在ActionScript中持久存储本地数据,您可以使用“SharedObject”类。在JavaScript中,简单的替换是localStorage API,它允许存储字符串以供以后检索,幸存的页面重新加载。

保存数据非常简单:

var progress = 15;
localStorage.setItem('myGame.progress', progress);
请注意,在上面的示例中,'progress'变量(数字)将转换为字符串。

加载也很简单,但请记住,检索到的值将是字符串,如果它们不存在则为null。

var progress = parseInt(localStorage.getItem('myGame.progress')) || 0;
这里我们确保返回值是一个数字。如果它不存在,那么0将被分配给'progress'变量。

您还可以存储和检索更复杂的结构,例如,JSON:

var stats = {'goals': 13, 'wins': 7, 'losses': 3, 'draws': 1
};
localStorage.setItem('myGame.stats', JSON.stringify(stats));

var stats = JSON.parse(localStorage.getItem('myGame.stats')) || {};
在某些情况下,'localStorage'对象将不可用。例如,使用file://协议或在私有窗口中加载页面时。您可以使用'try and catch'语句来确保您的代码继续工作并使用默认值,如下例所示:

try {
    var progress = localStorage.getItem('myGame.progress');
} catch (exception) {
  // localStorage not available, use default values
}
另一件需要记住的事情是存储的数据是按域保存的,而不是按URL保存的。因此,如果存在许多游戏托管在单个域上的风险,那么在保存时最好使用前缀(命名空间)。在上面的例子中,'myGame。' 是一个前缀,您通常希望将其替换为游戏名称。

如果您的游戏嵌入在iframe中,那么localStorage将不会在iOS上保留。在这种情况下,您需要将数据存储在父iframe中。

将Flash游戏转换为HTML5:自定义默认着色器

自定义默认着色器可用于替换Phaser和PixiJS中的着色方法。坦克在击中时会闪烁白色

当Phaser和PixiJS渲染你的精灵时,他们使用一个简单的内部片段着色器。它没有很多功能,因为它是为速度量身定制的。但是,您可以为您的目的替换该着色器。例如,您可以利用它来检查透支或支持更多渲染功能。下面是如何向Phaser v2提供您自己的默认片段着色器的示例。


function preload() {
  this.load.shader('filename.frag', 'shaders/filename.frag');
}
function create() {
  var renderer = this.renderer;
  var batch = renderer.spriteBatch;
  batch.defaultShader = 
  new PIXI.AbstractFilter(this.cache.getShader('filename.frag'));
  batch.setContext(renderer.gl);
}

自定义默认着色器可用于替换Phaser和PixiJS中的默认着色方法。在Phaser和PixiJS中着色通过将纹理像素乘以给定的颜色来工作。乘法总是使颜色变暗,这显然不是问题; 它与Flash着色完全不同。对于我们的一款游戏,我们需要实现类似于Flash的着色,并决定使用自定义默认着色器。下面是这样一个片段着色器的示例:

// Specific tint variant, similar to the Flash tinting that adds
// to the color and does not multiply. A negative of a color
// must be supplied for this shader to work properly, i.e. set
// sprite.tint to 0 to turn whole sprite to white.
precision lowp float;
varying vec2 vTextureCoord;
varying vec4 vColor;
uniform sampler2D uSampler;
void main(void) {
  vec4 f = texture2D(uSampler, vTextureCoord);
  float a = clamp(vColor.a, 0.00001, 1.0);
  gl_FragColor.rgb = f.rgb * vColor.a + clamp(1.0 - vColor.rgb/a, 0.0, 1.0) * vColor.a * f.a;
  gl_FragColor.a = f.a * vColor.a;
}
此着色器通过向色调添加基色来减轻像素。为此,您需要提供所需颜色的底片。因此,为了获得白色,您需要设置: 

sprite.tint = 0x000000;  // This colors the sprite to white
Sprite.tint = 0x00ffff;  // This gives red
07.检查透支
将Flash游戏转换为HTML5:Overdraw shader

左边的图片显示了玩家如何看到游戏,而右边的图片显示了将透支着色器应用于同一场景的效果还可以利用替换默认着色器来帮助调试。下面我们解释了如何使用这样的着色器检测过度绘制。当屏幕上的许多或所有像素被多次渲染时,会发生过度绘制。例如,许多对象占据相同的位置并且一个在另一个上呈现。GPU每秒可以渲染多少像素被描述为填充率。现代桌面GPU对于通常的2D目的而言具有过高的填充率,但是移动的GPU要慢得多。

通过使用以下方法替换PixiJS和Phaser中的默认全局片段着色器,有一种简单的方法可以找出屏幕上每个像素的写入次数:

void main(void) {
  gl_FragColor.rgb += 1.0 / 7.0;
}
此着色器可淡化正在处理的像素。数字7.0表示将像素变为白色需要多少次写入; 你可以根据自己的喜好调整这个数字。换句话说,屏幕上的较亮像素被写入数次,并且白色像素被写入至少七次。此着色器还有助于找到由于某种原因仍然呈现的“不可见”对象,以及需要剥离的具有过多透明区域的精灵(GPU仍然需要处理纹理中的透明像素)。

图像的左侧部分是游戏中的场景,而右侧显示相同的场景,顶部显示Phaser物理调试叠加层。物理引擎是一个中间件,负责模拟物理实体(通常是刚体动力学)及其碰撞。物理引擎模拟2D或3D空间,但不能同时模拟两者。典型的物理引擎将提供:

通过设定速度,加速度,关节和马达来进行物体移动;检测各种形状类型之间的碰撞;计算碰撞响应,即两个物体碰撞时应如何反应。有一个Phaser插件可以很好地用于此目的。Box2D也用于Unity游戏引擎和GameMaker Studio 2。

虽然物理引擎会加速您的开发,但您需要付出代价:降低运行时性能。检测冲突和计算响应是CPU密集型任务。您可能会限制在手机场景中的数十个动态对象或面临降级性能,以及低于60 FPS的帧速率降低。

如果您在.fla文件中有Flash游戏声音效果,则无法从GUI导出它们(至少在Adobe Animate CC 2017中没有),因为缺少用于此目的的菜单选项。但还有另一种解决方案 - 专用脚本就是这样做的:

function normalizeFilename(name) {
  // Converts a camelCase name to snake_case name
  return name.replace(/([A-Z])/g, '_$1').replace(/^_/, '').toLowerCase();
}
function displayPath(path) {
  // Makes the file path more readable
  return unescape(path).replace('file:///', '').replace('|', ':');
}
fl.outputPanel.clear();
if (fl.getDocumentDOM().library.getSelectedItems().length > 0)
  // Get only selected items
  var library = fl.getDocumentDOM().library.getSelectedItems();
else
  // Get all items
  var library = fl.getDocumentDOM().library.items;
// Ask user for the export destination directory
var root = fl.browseForFolderURL('Select a folder.');
var errors = 0;
for (var i = 0; i < library.length; i++) {
  var item = library[i];
  if (item.itemType !== 'sound')
  continue;
  var path = root + '/';
  if (item.originalCompressionType === 'RAW')
  path += normalizeFilename(item.name.split('.')[0]) + '.wav';
  else
  path += normalizeFilename(item.name);
  var success = item.exportToFile(path);
  if (!success)
  errors += 1;
  fl.trace(displayPath(path) + ': ' + (success ? 'OK' : 'Error')); 
}
fl.trace(errors + ' error(s)');
如何使用脚本导出声音文件:

将上面的代码保存为计算机上的.jsfl文件。使用Adobe Animate打开.fla文件。从顶部菜单中选择“命令”>“运行命令”,然后在打开的对话框中选择脚本。现在弹出另一个对话文件,用于选择导出目标目录。完成!您现在应该在指定的目录中有WAV文件。剩下要做的就是将它们转换为MP3,OGG或AAC。

好的旧MP3格式又回来了,因为一些专利已经过期,现在每个浏览器都可以解码和播放MP3。这使得开发变得更容易,因为最终不需要准备两种单独的音频格式。以前你需要OGG和AAC文件,而现在MP3就足够了。

尽管如此,您还需要记住有关MP3的两个重要事项:

MP3需要在加载后解码,这可能非常耗时,尤其是在移动设备上。如果在加载所有资源后看到暂停,则可能意味着正在解码MP3。毫无问题地播放循环MP3有点问题。解决方案是使用mp3loop,在 Compu Phase发布的这篇文章中阅读更多内容。

版权声明:转载此文章须经 领创时代 同意,并请附上 领创时代 及本页链接http://www.leadnov.com/newsItem.aspx?id=162
创造品牌视觉体验 X 创新IT技术赋能企业
领创帮助您创新品牌战略,让品牌成为最具价值的资产。
中国·山东 青岛市市北区郑州路43号橡胶谷A栋
热线:175 6191 5976
微信:leadnov
Copyright © 2018-2020 leadnov.com 版权所有
鲁公网安备37020302372323
ICP证: 鲁ICP备18056479号

关注领创公众平台

添加官方微信

175 6191 5976