《祖玛ZUMA》分享技术思路和贝塞尔曲线细节实现,匀速加减速

太顶了,真的太顶了!

强啊!!!

大佬有没有粉丝群,求加入!!!

大佬,是否有长期合作意向?

说明一下:看到很多人对祖玛的技术细节很感兴趣,但是我这个游戏作为一个上线多年,没有管理没有维护的游戏,截止目前游戏的收入还可以,所以纯粹处于私人利益的考虑,短期内不考虑开源。希望各位尽管未曾谋面的远方的同行们理解哈。

至于技术实现细节,我的帖子里都已经交代的很清楚了,因为涉及一点数学运算,代码实现可能只是增加了一丢丢的难度。

2赞

Mark一下

可以看下laya代码

1赞

import { Point } from “./Point”;

/**

  • @private

  • 计算贝塞尔曲线的工具类。
    */
    export class Bezier {

    /**

    • 工具类单例
      /
      static I: Bezier = new Bezier();
      /
      * @private /
      private _controlPoints: any[] = [new Point(), new Point(), new Point()];
      /
      * @private */
      private _calFun: Function = this.getPoint2;

    /** @private */
    private _switchPoint(x: number, y: number): void {
    var tPoint: Point = this._controlPoints.shift();
    tPoint.setTo(x, y);
    this._controlPoints.push(tPoint);
    }

    /**

    • 计算二次贝塞尔点。
      */
      getPoint2(t: number, rst: any[]): void {
      //二次贝塞尔曲线公式
      var p1: Point = this._controlPoints[0];
      var p2: Point = this._controlPoints[1];
      var p3: Point = this._controlPoints[2];
      var lineX: number = Math.pow((1 - t), 2) * p1.x + 2 * t * (1 - t) * p2.x + Math.pow(t, 2) * p3.x;
      var lineY: number = Math.pow((1 - t), 2) * p1.y + 2 * t * (1 - t) * p2.y + Math.pow(t, 2) * p3.y;
      rst.push(lineX, lineY);
      }

    /**

    • 计算三次贝塞尔点
      */
      getPoint3(t: number, rst: any[]): void {
      //三次贝塞尔曲线公式
      var p1: Point = this._controlPoints[0];
      var p2: Point = this._controlPoints[1];
      var p3: Point = this._controlPoints[2];
      var p4: Point = this._controlPoints[3];
      var lineX: number = Math.pow((1 - t), 3) * p1.x + 3 * p2.x * t * (1 - t) * (1 - t) + 3 * p3.x * t * t * (1 - t) + p4.x * Math.pow(t, 3);
      var lineY: number = Math.pow((1 - t), 3) * p1.y + 3 * p2.y * t * (1 - t) * (1 - t) + 3 * p3.y * t * t * (1 - t) + p4.y * Math.pow(t, 3);
      rst.push(lineX, lineY);
      }

    /**

    • 计算贝塞尔点序列
      */
      insertPoints(count: number, rst: any[]): void {
      var i: number;
      count = count > 0 ? count : 5;
      var dLen: number;
      dLen = 1 / count;
      for (i = 0; i <= 1; i += dLen) {
      this._calFun(i, rst);
      }
      }

    /**

    • 获取贝塞尔曲线上的点。
    • @param pList 控制点[x0,y0,x1,y1…]
    • @param inSertCount 每次曲线的插值数量
      */
      getBezierPoints(pList: any[], inSertCount: number = 5, count: number = 2): any[] {
      var i: number, len: number;
      len = pList.length;
      if (len < (count + 1) * 2) return [];
      var rst: any[] = [];
      switch (count) {
      case 2:
      this._calFun = this.getPoint2;
      break;
      case 3:
      this._calFun = this.getPoint3;
      break;
      default:
      return [];
      }
      while (this._controlPoints.length <= count) {
      this._controlPoints.push(Point.create());
      }
      for (i = 0; i < count * 2; i += 2) {
      this._switchPoint(pList[i], pList[i + 1]);
      }
      for (i = count * 2; i < len; i += 2) {
      this._switchPoint(pList[i], pList[i + 1]);
      if ((i / 2) % count == 0) this.insertPoints(inSertCount, rst);
      }
      return rst;
      }
      }
1赞

import { Pool } from “…/utils/Pool”

/**

  • Point 对象表示二维坐标系统中的某个位置,其中 x 表示水平轴,y 表示垂直轴。
    */
    export class Point {

    /临时使用的公用对象。*/
    static TEMP: Point = new Point();
    /
    @private 全局空的point对象(x=0,y=0),不允许修改此对象内容*/
    static EMPTY: Point = new Point();

    /**该点的水平坐标。/
    x: number;
    /**该点的垂直坐标。
    /
    y: number;

    /**

    • 根据指定坐标,创建一个新的 Point 对象。
    • @param x (可选)水平坐标。
    • @param y (可选)垂直坐标。
      */
      constructor(x: number = 0, y: number = 0) {
      this.x = x;
      this.y = y;
      }

    /**

    • 从对象池创建
      */
      static create(): Point {
      return Pool.getItemByClass(“Point”, Point);
      }

    /**

    • Point 的成员设置为指定值。
    • @param x 水平坐标。
    • @param y 垂直坐标。
    • @return 当前 Point 对象。
      */
      setTo(x: number, y: number): Point {
      this.x = x;
      this.y = y;
      return this;
      }

    /**

    • 重置
      */
      reset(): Point {
      this.x = this.y = 0;
      return this;
      }

    /**

    • 回收到对象池,方便复用
      */
      recover(): void {
      Pool.recover(“Point”, this.reset());
      }

    /**

    • 计算当前点和目标点(x,y)的距离。
    • @param x 水平坐标。
    • @param y 垂直坐标。
    • @return 返回当前点和目标点之间的距离。
      */
      distance(x: number, y: number): number {
      return Math.sqrt((this.x - x) * (this.x - x) + (this.y - y) * (this.y - y));
      }

    /**返回包含 x 和 y 坐标的值的字符串。*/
    toString(): string {
    return this.x + “,” + this.y;
    }

    /**

    • 标准化向量。
      */
      normalize(): void {
      var d: number = Math.sqrt(this.x * this.x + this.y * this.y);
      if (d > 0) {
      var id: number = 1.0 / d;
      this.x *= id;
      this.y *= id;
      }
      }

    /**

    • copy point坐标
    • @param point 需要被copy的point
      */
      copy(point: Point): Point {
      return this.setTo(point.x, point.y);
      }
      }
1赞