utility.js

import * as PIXI from 'pixi.js';
import _ from 'lodash';
import { loadedScript } from './variable';

/**
 * Gamify 라이브러리 제작에 필요한 각종 함수들을 모아놓은 클래스
 * @alias Utility
 */
export default class Utility {
  /**
   * [r,g,b] 형태의 rgb값을 hex값으로 변경시켜줌
   * <p>static 함수
   * @param {array} rgb [r,g,b]
   * @memberof Utility
   * @returns {number} hex
   * @instance
   */
  static rgb2hex(rgb) {
    const rgbClone = _.cloneDeep(rgb);
    for (let i = 0; i < 3; i++) {
      rgbClone[i] /= 255;
    }
    return PIXI.utils.rgb2hex(rgbClone);
  }

  /**
   * 0x000000 형태의 hex값을 '0x000000'의 문자열로 변경시켜줌
   * <p>static 함수
   * @param {number} hex hex 값
   * @memberof Utility
   * @returns {string} hex string
   * @instance
   */
  static hex2string(hex) {
    return PIXI.utils.hex2string(hex);
  }

  /**
   * javascript 상에서 다른 script를 로드시켜줌
   * <p>static 함수
   * @param {string} src 로드할 script 주소
   * @memberof Utility
   * @returns {Promise}
   * @instance
   */
  static loadScript(src) {
    if (!_.includes(loadedScript, src)) {
      loadedScript.push(src);
      return new Promise((resolve) => {
        const script = document.createElement('script');
        script.src = src;
        script.type = 'text/javascript';
        script.async = true;
        script.onload = resolve;
        document.body.appendChild(script);
      });
    }
    return true;
  }

  /**
   * 최대공약수를 구해줌
   * <p>static 함수
   * @param {number} a 최대공약수를 구할 수 1
   * @param {number} b 최대공약수를 구할 수 2
   * @memberof Utility
   * @returns {number} 최대공약수
   * @instance
   */
  static gcd(a, b) {
    return (b === 0) ? a : this.gcd(b, a % b);
  }

  /**
   * PIXI object 자동 생성
   * <p>static 함수
   * @param {object} option Gamify에서 생성한 option 화면의 최대사이즈 때문에 필요
   * @param {boolean} pointerEvents pointerEvents의 유무
   * @memberof Utility
   * @returns {PIXI} PIXI
   * @instance
   */
  static makePixi(option, pointerEvents) {
    PIXI.utils.skipHello();
    const pixi = new PIXI.Application({
      width: option.rootSize.width,
      height: option.rootSize.height,
      transparent: true,
      autoResize: true, // resize 시에만 동작함 (see http://www.html5gamedevs.com/topic/30645-rendererautoresize-doesnt-seem-to-work/),
      antialias: true,
      // resolution: 2,
    });

    pixi.renderer.resize(option.rootSize.width, option.rootSize.height);
    pixi.view.style.width = option.rootSize.width;
    pixi.view.style.height = option.rootSize.height;
    pixi.view.style.position = 'absolute';
    pixi.view.style.zIndex = 2;
    if (pointerEvents === undefined || pointerEvents === false) {
      pixi.view.style.pointerEvents = 'none';
    }
    document.getElementById(option.domId).appendChild(pixi.view);
    return pixi;
  }

  /**
   * PIXI의 zOrder를 통해 정렬
   * <p>static 함수
   * @param {PIXI} pixi PIXI 오브젝트
   * @memberof Utility
   * @instance
   */
  static arrangePixiZOrder(pixi) {
    pixi.stage.children.sort((a, b) => {
      a.zOrder = a.zOrder || 0;
      b.zOrder = b.zOrder || 0;
      return b.zOrder - a.zOrder;
    });
  }

  /**
   * 한 지점에서 각도와 거리를 통해 새로운 지점을 구함
   * <p>static 함수
   * @param {object} point 시작지점
   * @param {number} angle 각도
   * @param {number} distance 거리
   * @memberof Utility
   * @returns {object} result
   * @instance
   */
  static findNewPointByAngleWithDistance(point, angle, distance) {
    const result = {};
    result.x = Math.cos(angle * Math.PI / 180) * distance + point.x;
    result.y = Math.sin(angle * Math.PI / 180) * distance + point.y;

    return result;
  }

  /**
   * 두 지점 사이의 각도를 구함
   * <p>static 함수
   * @param {object} p1 1번 지점
   * @param {number} p2 2번 지점
   * @memberof Utility
   * @returns {object} result
   * @instance
   */
  static findAngleBetweenTwoPoints(p1, p2) {
    return Math.atan2(p2.y - p1.y, p2.x - p1.x);
  }

  /**
   * 두 지점 사이의 거리를 구함
   * <p>static 함수
   * @param {object} p1 1번 지점
   * @param {number} p2 2번 지점
   * @memberof Utility
   * @returns {object} result
   * @instance
   */
  static findDistanceBetweenTwoPoints(p1, p2) {
    const x = p1.x - p2.x;
    const y = p1.y - p2.y;
    return Math.sqrt((x ** 2) + (y ** 2));
  }

  /**
   * 지정된 색상에서 지정된 % 만큼 밝은 값을 구함
   * <p>static 함수
   * @param {number} hex 색상 값
   * @param {number} percent %
   * @memberof Utility
   * @returns { string } hex
   * @instance
   */
  static increaseBrightness(hex, percent) {
    // strip the leading # if it's there
    hex = hex.replace(/^\s*0x|\s*$/g, '');

    // convert 3 char codes --> 6, e.g. `E0F` --> `EE00FF`
    if (hex.length === 3) {
      hex = hex.replace(/(.)/g, '$1$1');
    }

    const r = parseInt(hex.substr(0, 2), 16);
    const g = parseInt(hex.substr(2, 2), 16);
    const b = parseInt(hex.substr(4, 2), 16);

    // eslint-disable-next-line no-bitwise
    const result = `${((0 | (1 << 8) + r + (256 - r) * percent / 100).toString(16)).substr(1)}${((0 | (1 << 8) + g + (256 - g) * percent / 100).toString(16)).substr(1)}${((0 | (1 << 8) + b + (256 - b) * percent / 100).toString(16)).substr(1)}`;
    return parseInt(result, 16);
  }
}