Cocos 2.x- 屏幕适配、对齐策略

发布时间 2023-11-04 22:27:34作者: 米虫2022

《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

总结一下主要有两点吧:

  1. 设计分辨率宽高比大于屏幕分辨率,适配高度避免黑边
  2. 设计分辨率宽高比小于屏幕分辨率,适配宽度避免黑边

这里的设计分辨率就是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的了解还不是很多,后续在慢慢阅读文档继续完善。