吐槽一个Vec2/3的设计问题

Vec3能不能继承Vec2啊,现在这样挺烦的,有些是Vec2,例如TOUCH事件,有些又是Vec3,例如Node的坐标,搞到要转来转去。
做2D游戏实际也是用Vec2的需求多,但涉及ui又得转Vec3.
要是Vec3是继承Vec2的,或者2D的UI可以接收Vec2,例如setPosition的时候,如果传Vec2,就默认z是0,那就方便多了。

2赞

确实,得到vec2或vec3的,偏要转换一下 :rofl:

1赞

最主要的是vec3构造不能传vec2,vec2构造不能传vec3,每次都要(v.x, v.y)
@jare 接口改进下?比如 cc.v2(cc.v3()),cc.v3(cc.v2());

要啥自行车

终于有人吐槽这个问题了,哈哈

吐槽+1!!!!

无法继承,因为不满足 is-a,能继承早就继承了。

// vec2
public cross (other: Vec2) {
    return this.x * other.y - this.y * other.x;
}

// vec3
public cross (other: Vec3) {
    const { x: ax, y: ay, z: az } = this;
    const { x: bx, y: by, z: bz } = other;

    this.x = ay * bz - az * by;
    this.y = az * bx - ax * bz;
    this.z = ax * by - ay * bx;
    return this;
}

计算方式,和返回值都不一样,vec2 期望返回一个 number,并且是用 xy 计算出来。显然无法用 vec3 替换。硬要继承的话,就需要修改 API,把 vec3 或者 vec2 的 cross 改成别的函数名,这样又要被开发者骂乱改 API 了。

同样问题出现在 angle/signAngle 上,vec3 没有这个概念,也就没有实现这些函数。rotate 也没实现。

(当然,is-a 不能用,不代表 like-a 也用不了,大部分情况下用 IVec2Like 是可以取代的。这个我们会继续跟进优化)

new、cc.v2、cc.v3 构造可以优化一下吧,每次都得手动打 x, y,转换次数一多直接人崩溃,之前经常遇到,然后我把所有用 vec2 的全改成 vec3 了,最好是支持传入 {x?: number, y?: number, z?: number} 这样的类型数据,比如可以直接用 cc.v2(cc.size()) 直接初始化

返回值不同算什么障碍,用泛型就可以解决了吧,反正写法很多,我随便举个例子
Vec2<T = number>
cross():T

Vec3 < T = Vec3> extends Vec2 < T >
cross():T

angle/signAngle这些不存在的函数,泛型类型用never

嗯嗯,已转达给负责这块的小伙伴了,谢谢反馈

一个是 number,一个是 Vec3,用泛型怎么解决?用户期望是一个 number(vec2 返回的),结果实际是 object(vec3 返回的)

image image

这里如果实例里的参数也是IVec2Like接口的话,应该能解决大部分需要转换的问题吧?

2赞

touch.getUILocation是个Vec2,但UITransform.convertToNodeSpace偏偏又要Vec3,每次写这个坐标点转换的时候我都想骂娘

3赞

确实这个很烦

1赞

我同意muzzik的说法,我们并不是一定要继承,只是让常用的接口,转换别那么麻烦。哪怕提供一个便捷转换方法也好,每次写毫无意义的cc.vec2与cc.vec3转换真是太烦人了。总不能希望我们写下面的代码吧?

function vec2To3(pos:cc.Vec2):cc.Vec3{
    return cc.v3(pos.x, pos.y)
}

function vec3To2(pos:cc.Vec3):cc.Vec2{
    return cc.v2(pos.x, pos.y);
}

可以在这里讨论

其实很多api的参数只需要是IVec2Like或者IVec3Like就行了,根本没必要严格的是Vec2或Vec3,改下这种api的设计根本就不需要牵扯到转换

1赞

哈哈哈,你不懂这帮程序员,这个根本没人去讨论,没有比论坛讨论起来更方便舒服的地方了

去那里,会暴露出我英文太烂的弱点。
我看了讨论主题,如果然我自己选,我选下面的代码。理由是可以链式调用,结合现有的API,写起来方便。 纯个人观点,不喜勿喷。

cc.Vec2.prototype.toVec3 = function ():cc.Vec3 {
    return cc.v3(this.x, this.y);
}

cc.Vec3.prototype.toVec2 = function ():cc.Vec2 {
   return cc.v2(this.x, this.y);
}

this.node.position = this.node.getPosition().toVec3();
2赞

可能会引起性能问题……