当前位置:首页>编程日记>正文

Hilo开发H5小游戏踩坑笔记

第一次开发小游戏,用的是Hilo框架。由于项目开发时间比较紧张,对游戏和CANVAS都没有了解过。代码虽然写的很烂,但是还是记录下踩过的坑吧!本文为碎碎念模式,并不深入,写错的地方希望多多指点。

一、CANVAS横屏适配处理

游戏是微信内的一款横屏游戏。如果强制横屏,提示用户去控制横竖屏开关并不友好。

解决方案,游戏场景做成如下图紫色部分结构,游戏宽高和手机屏幕调换。如果手机为竖屏,那么将游戏旋转90°即可。

注:所述【横屏】为用户打开了允许横屏的开关并横屏,真正的横屏。

代码如下所示:

let width = document.documentElement.clientWidth;
let height =  document.documentElement.clientHeight;
let box =  document.getElementsByTagName('canvas');
let style = '';
// 竖屏
if (width < height) {style += `width:${height}px;`;style += `height:${width}px;`;style += '-webkit-transform: rotate(90deg); transform: rotate(90deg);';// 注意旋转中点的处理style += `-webkit-transform-origin: ${width / 2}px ${width / 2}px;`;style += `transform-origin: ${width / 2}px ${width / 2}px;`;
}if (box.length) {box[0].style.cssText = style;
}
复制代码

当用户开启了横屏开关,如果用户横屏,那就将游戏场景旋转0°即可,也就是恢复最初的样子。如下:

// 横屏
if (width > height) {style += `width:${width}px;`; // 注意旋转后的宽高切换style += `height:${height}px;`;style += '-webkit-transform: rotate(0); transform: rotate(0);';style += '-webkit-transform-origin: 0 0;';style += 'transform-origin: 0 0;';
}if (box.length) {box[0].style.cssText = style;
}
复制代码

横屏没想象那么顺利,我们的游戏是在微信场景。当用户开启横屏开关并横屏后,微信内置浏览器头也会占一大部分区域。这样我们的游戏场景旋转后明显是显示不全的。

解决方案就是利用Hilo的api resize下舞台

// 解决微信横屏浏览器头部 导致高度变化的问题
this.stage.resize(height, width, true);   
复制代码

最后有几个注意点:

1、注意旋转过程中的宽高切换2、注意单位适配问题3、注意微信浏览器头,就因为这个头的变化。整个游戏都需要处理,所以还是尽量不要自己处理。。。
复制代码

参考文章

二、点击事件失效

如下图所示,游戏结束场景的2个按钮。

左侧旋转90°后变成右侧横屏,但是竖屏下的横屏(也就是旋转90°得来的)【再来一次】按钮点击事件会失效,但是点击红色区域(没有按钮,大致绘制并不精准)部分这个时间会被触发。

而用户横屏(开启了横屏开关,自然横屏)【再来一次】按钮点击事件不会失效。

绘制时坐标以游戏场景左上角为(0,0),而旋转90°后坐标以游戏场景左下角为(0,0)。因为旋转90°后游戏场景左下角变成了视觉上的左上角。因此竖屏下的横屏点击红色区域生效就是因为,Hilo的点击事件是绑定在元素绘制时坐标区域上(猜测,没有看源码)。旋转后,按钮的点击事件生效区间就变成了根据绘制的x、y也就是红色区域。

那么如何解决这个问题,如上图所示,旋转后的x、y如图中蓝色字所示。可以算出

// 再玩一次按钮
const start = this.gameOverScene.getChildById('start'); 
// 再玩一次按钮 新的x = 游戏画布宽度 - 绘制的y - 按钮的高度
const startNewX = this.width - start.y - start.height ;
// 再玩一次按钮 新的y = 绘制的x
const startNewY = start.x;
// 监听舞台点击事件
this.stage.on(Hilo.event.POINTER_START, (e) => {// 利用新的x、y 和按钮自身的高度和宽度 判断是否点击在按钮区域if ((e.stageX > startNewX && e.stageX < startNewX + start.height) &&(e.stageY > startNewY && e.stageY < startNewY + start.width)) {// 在玩一次逻辑处理}
)};
复制代码

【再玩一次】按钮点击事件解决了,但是事情没有那么简单。

给另一个【分享】按钮加上事件,what?无论横屏还是竖屏点击事件都不生效。至少【再玩一次】按钮事件还是生效的,只是不准罢了。

原因,观察上述图。【分享】按钮在初始化的过程中是在游戏画布右侧,也就是手机屏幕外部。经过测试发现,发现绘制时在手机屏幕外的区域点击事件都不会生效。解决方法如【再玩一次】,无论横屏还是竖屏都计算坐标判断。

三、音乐播放兼容

Hilo的HTMLAudio声音播放模块,官方文档表示【使用限制:iOS平台需用户事件触发才能播放,很多Android浏览器仅能同时播放一个音频。】但是目前使用来看,浏览器测试OK,绝大部分手机都不能正常播放。解决方案,采用DOM的audio,但是同样iOS平台需用户事件触发才能播放。因此最终的解决方案就是进入游戏之前或者某个合适的环节获取所有的音乐,先播放再暂停。用户不会感知,可以完美解决。如下:

// html
<audio id="audio"  src="xxx.mp3" preload="auto"></audio>
// dom为获取
const dom = document.getElementById('audio');
dom.play();
dom.pause();
复制代码

四、部分机型游戏场景显示不全

游戏中可能有某些元素是经常复用的,因此会单独切出来。如下图左侧

如上图右侧所示效果,最开始的实现方式如下。在初始化的时候就将公用元素Y轴截断展示,这个效果看似OK,但是在测试阶段发现某些iPhone手机不能显示这2个元素。

new Hilo.Bitmap({// 绘制的图片image: 'imgurl', // 测试坐标,非精准坐标rect: [0, 100, 50, 300],y: 0,
});
new Hilo.Bitmap({// 绘制的图片image: 'imgurl', // 测试坐标,非精准坐标rect:[0, 150, 50, 300],y: 0,
});复制代码

查看Hilo源码绘制图片是用CanvasRenderingContext2D.drawImage方法。

CanvasRenderingContext2D.drawImage() 是浏览器原生提供的在 canvas 上绘制图片的方法。

其有以下三种参数形式(详细用法说明及演示可见 MDN):

  1. ctx.drawImage(image, dx, dy);
    ctx.drawImage(image, dx, dy, dWidth, dHeight);
    ctx.drawImage(image, sx, sy, sWidth, sHeight, dx, dy, dWidth, dHeight);
    复制代码

参数意义
sx, sy源图像的选择区域的偏移量
sWidth, sHeight源图像的选择区域的宽高
dx, dy目标canvas的选择区域的偏移量
dWidth, dHeight目标canvas的选择区域的宽高

注:

  1. 在 Chrome 和 Firefox 下,最终的选择区域超出源图像的部分不会被绘制。
  2. 在 IE 和 Edge 下,最终的选择区域超出源图像的部分会用图像的边界像素来填充。
  3. Safari 7.1 额外要求 sx + sWidthsy + sHeight 不超过源图像的宽高,否则 drawImage() 函数不会绘制任何图像。(未在更高版本的 Safari 上测试)
  4. 在支持 canvas 的老版本的 Firefox 上,有着和 IE 等浏览器类似的对 sx, sy, sWidth, sHeight 的限制,在新版本中,这些限制已经被移除。

而我们的元素在部分机型上不能显示就是因为触发了第3点坑。修复代码如下,通过完整的绘制图片,然后通过元素的坐标来达到目标样式。

new Hilo.Bitmap({// 绘制的图片image: 'imgurl', // 测试坐标,非精准坐标rect: [0, 0, 50, 300],y: -100,
});
new Hilo.Bitmap({// 绘制的图片image: 'imgurl', // 测试坐标,非精准坐标rect:[0, 0, 50, 300],y: -150,
});
复制代码

参考文章

五、碰撞检测,撞击坐标不准确

用Hilo最开始开心的一点也是碰撞检测不需要自己写,hitTestObject检测object参数指定的对象是否与其相交。因此撞击区域可以书写撞击坐标。

// 给如下图中的一个多边形实行撞击坐标
new Hilo.Bitmap({// 绘制的图片image: 'imgurl', // 测试坐标,非精准坐标rect: [0, 0, 50, 300],y: -100,boundsArea: [// 测试坐标,非精准坐标,图中红点的坐标,从左到右{x: 0, y: 0},{x: 0, y: 100},{x: 100, y: 100},{x: 100, y: 200},{x: 200, y: 200},{x: 200, y: 100},{x: 300, y: 100},{x: 300, y: 0},]
});
复制代码

理想中应该是如下黄色区域构成的碰撞检测区域。

而实际却是如下黄色区域,空气墙???用户反馈为什么没撞到就死翘翘了。(看了Hilo碰撞检测这部分的实现源码,没太看懂多边形的处理。。)

解决办法,类似雪碧图使用,恩...主要是懒得切图

new Hilo.Bitmap({// 绘制的图片image: 'imgurl', // 测试坐标,非精准坐标rect: [0, 0, 100, 100],y: 0,boundsArea: [// 测试坐标,非精准坐标,图中红点的坐标,从左到右{x: 0, y: 0},{x: 0, y: 100},{x: 100, y: 100},{x: 100, y: 0},]
});
new Hilo.Bitmap({// 绘制的图片image: 'imgurl', // 测试坐标,非精准坐标rect: [100, 0, 100, 200],y: 0,boundsArea: [// 测试坐标,非精准坐标,图中红点的坐标,从左到右{x: 0, y: 0},{x: 0, y: 200},{x: 100, y: 200},{x: 100, y: 0},]
});
new Hilo.Bitmap({// 绘制的图片image: 'imgurl', // 测试坐标,非精准坐标rect: [200, 0, 100, 100],y: 0,boundsArea: [// 测试坐标,非精准坐标,图中红点的坐标,从左到右{x: 0, y: 0},{x: 0, y: 100},{x: 100, y: 100},{x: 100, y: 0},]
});
复制代码

其实就是将1张图裁剪成了3张图,裁剪出来的区域撞击坐标都中规中矩。过于不规则的图形只能尽量写的粗糙一些。

这么轻松就解决了吗???当然NO!!!回顾下第四点,部分机型游戏场景显示不全。上面裁剪的3张图里,最后一张图又触发了safari的bug。o(╥﹏╥)o,所以还是乖乖切图,或者雪碧图留一点安全区域吧!

而且后来我才知道雪碧图对于CANVAS来说更耗性能,还不如多切点图呢~


http://www.coolblog.cn/news/99a41c3a5ce49611.html

相关文章:

  • asp多表查询并显示_SpringBoot系列(五):SpringBoot整合Mybatis实现多表关联查询
  • s7day2学习记录
  • 【求锤得锤的故事】Redis锁从面试连环炮聊到神仙打架。
  • 矿Spring入门Demo
  • 拼音怎么写_老师:不会写的字用圈代替,看到孩子试卷,网友:人才
  • Linux 实时流量监测(iptraf中文图解)
  • Win10 + Python + GPU版MXNet + VS2015 + RTools + R配置
  • 美颜
  • shell访问php文件夹,Shell获取某目录下所有文件夹的名称
  • 如何优雅的实现 Spring Boot 接口参数加密解密?
  • LeCun亲授的深度学习入门课:从飞行器的发明到卷积神经网络
  • Mac原生Terminal快速登录ssh
  • java受保护的数据与_Javascript类定义语法,私有成员、受保护成员、静态成员等介绍...
  • mysql commit 机制_1024MySQL事物提交机制
  • 支撑微博千亿调用的轻量级RPC框架:Motan
  • jquery 使用小技巧
  • 2019-9
  • 法拉利虚拟学院2010 服务器,法拉利虚拟学院2010
  • vscode pylint 错误_将实际未错误的py库添加到pylint白名单
  • 科学计算工具NumPy(3):ndarray的元素处理
  • 工程师在工作电脑存 64G 不雅文件,被公司开除后索赔 41 万,结果…
  • linux批量创建用户和密码
  • newinsets用法java_Java XYPlot.setInsets方法代碼示例
  • js常用阻止冒泡事件
  • 气泡图在开源监控工具中的应用效果
  • 各类型土地利用图例_划重点!国土空间总体规划——土地利用
  • php 启动服务器监听
  • dubbo简单示例
  • 【设计模式】 模式PK:策略模式VS状态模式
  • [iptables]Redhat 7.2下使用iptables实现NAT
  • Ubuntu13.10:[3]如何开启SSH SERVER服务
  • CSS小技巧——CSS滚动条美化
  • JS实现-页面数据无限加载
  • 阿里巴巴分布式服务框架 Dubbo
  • 最新DOS大全
  • Django View(视图系统)
  • 阿里大鱼.net core 发送短信
  • 程序员入错行怎么办?
  • 两张超级大表join优化
  • 第九天函数
  • Linux软件安装-----apache安装
  • HDU 5988 最小费用流
  • Sorenson Capital:值得投资的 5 种 AI 技术
  • 《看透springmvc源码分析与实践》读书笔记一
  • 正式开课!如何学习相机模型与标定?(单目+双目+鱼眼+深度相机)
  • Arm芯片的新革命在缓缓上演
  • nagios自写插件—check_file
  • python3 错误 Max retries exceeded with url 解决方法
  • 行为模式之Template Method模式
  • 通过Spark进行ALS离线和Stream实时推荐