在《Cocos 2.x-Hello World 飞机大战游戏》,简单实现了一个Cocos 2.x Hello World 程序,但是在不同的机型的运行效果,会出现黑边的情况,在查看Cocos Creator的手册之后,发现了一个简单的解决方案,这里记录一下处理过程。
1. 环境搭建
为了不对原来的代码进行大的调整,这里单独创建了一个新的游戏场景进行测试,相关场景资源如下:
2. 多分辨率适配方案
在多分辨率适配方案中,官方文档提供了方案说明:
https://docs.cocos.com/creator/2.4/manual/zh/ui/multi-resolution.html
总结一下主要有两点吧:
- 设计分辨率宽高比大于屏幕分辨率,适配高度避免黑边
- 设计分辨率宽高比小于屏幕分辨率,适配宽度避免黑边
这里的设计分辨率就是Canvas中的Design Resolution
获取得到,至于屏幕分辨率,目前还不是很熟悉API,暂时使用cc.winSize
获取。
在上图的游戏脚本中,新增了一个GameSettingCC用于动态调整上诉的两种方案:
const { ccclass, property } = cc._decorator;
@ccclass
export default class GameSettingCC extends cc.Component {
onLoad() {
const canvas = this.node.getComponent(cc.Canvas);
const dr = canvas.designResolution.width / canvas.designResolution.height;
const wr = cc.winSize.width / cc.winSize.height;
if (dr > wr) {
canvas.fitHeight = true;
canvas.fitWidth = false;
} else {
canvas.fitHeight = false;
canvas.fitWidth = true;
}
cc.log("dr=" + dr, "wr=" + wr);
cc.log("fitHeigh=" + canvas.fitHeight, "fitWidth=" + canvas.fitWidth);
}
}
这个脚本挂在Canvas上,这样可以初步解决不同机型(分辨率不同)显示出现黑边的问题。
3. 对齐策略
通过简单地通过调整fitHeight或fitWidth可以适配不同分辨率的问题,但是无法解决UI元素在Canvas中的相对位置,在官方文档中发现对其策略
,可以用来解决这个问题,官方文档地址:
https://docs.cocos.com/creator/2.4/manual/zh/ui/widget-align.html
在飞机大战游戏中,分数这个UI元素就需要通过这种策略,来适配不同的分辨率问题:
给score
这个Label UI元素加上Widget组件,并调整其Top和Left为25px,
通过Widget配置边距,就可以解决不同分别率下,score
这个Label的位置错乱问题。
4. 位置计算
在新的游戏场景中,将所有节点元素都作为Canvas的子节点,一些计算需要调整一下,主要是坐标中心变了。
const { ccclass, property } = cc._decorator;
@ccclass
export default class PlayerCC extends cc.Component {
minX: number;
maxX: number;
minY: number;
maxY: number;
moving: boolean = false;
onLoad() {
const size = cc.winSize;
cc.log(size.width, size.height);
this.maxX = size.width / 2;
this.minX = -this.maxX;
this.maxY = size.height / 2;
this.minY = -this.maxY;
}
start() {
this.initializeTouchEvent();
}
initializeTouchEvent() {
this.node.on(cc.Node.EventType.TOUCH_START, () => (this.moving = true));
this.node.on(cc.Node.EventType.TOUCH_END, () => (this.moving = false));
this.node.on(cc.Node.EventType.TOUCH_MOVE, (e: cc.Event.EventTouch) => {
if (this.moving) {
let x = e.getLocationX() - this.maxX;
let y = e.getLocationY() - this.maxY;
cc.log(e.getLocationX(), e.getLocationY());
x = Math.max(this.minX + this.node.width / 2, x);
x = Math.min(this.maxX - this.node.width / 2, x);
y = Math.max(this.minY + this.node.height / 2, y);
y = Math.min(this.maxY - this.node.height / 2, y);
this.node.setPosition(x, y);
}
});
}
}
这里可能还有更好的解决方案,但就目前对Cocos2.x的了解还不是很多,后续在慢慢阅读文档继续完善。