碰撞、子弹路径、参考

这篇博客主要介绍了如何计算子弹的运动轨迹,并结合参考播放动画来理解这一过程。内容包括动态模拟和视觉呈现方面的细节。
摘要由CSDN通过智能技术生成


/**
 * @description 一些和显示相关的函数放到这里
 * @author (pdh)
 * @date 2020-11-05
 * @class ShowUtil
 */
class ShowUtil {
	private static instance: ShowUtil = null;
	private hurtColorFilter = null;
	private shadowColorFilter = null;
	private shadeColors: number[] = [];
	private shadeMap: {} = {};

	private constructor() {
	}


	public static getInstance() {
		if (!this.instance) {
			this.instance = new ShowUtil();
		}
		return this.instance;
	}

	/**
	 * @description 沿着中心翻转
	 * @author (pdh)
	 * @date 2020-11-05
	 * @param {egret.DisplayObject} entity
	 * @param {boolean} [flipX=false]
	 * @param {boolean} [flipY=false]
	 * @memberof ShowUtil
	 */
	public centerFlip(entity: egret.DisplayObject, flipX: boolean = false, flipY: boolean = false): void {
		if (!entity) {
			return;
		}

		if (entity.anchorOffsetX === 0 && flipX) {
			let offsetX = entity.width / 2.0;
			entity.anchorOffsetX = offsetX;
			entity.x += offsetX;
		}

		if (flipX) {
			entity.scaleX = entity.scaleX * (-1);
		}

		if (entity.anchorOffsetY === 0 && flipY) {
			let offsetY = entity.height / 2.0;
			entity.anchorOffsetY = offsetY;
			entity.y += offsetY;
		}

		if (flipY) {
			entity.scaleY = entity.scaleY * (-1);
		}
	}

	/**
	 * @description 更改锚点。更改后图标显示不移位,仍然按照原来位置显示,只是锚点更改了。
	 * @author (pdh)
	 * @date 2020-11-06
	 * @param {egret.DisplayObject} entity
	 * @param {number} anchorX
	 * @param {number} anchorY
	 * @memberof ShowUtil
	 */
	public setAnchor(entity: egret.DisplayObject, anchorX: number, anchorY: number): void {
		let oldAnchorX = entity.anchorOffsetX;
		let oldAnchorY = entity.anchorOffsetY;
		entity.anchorOffsetX = anchorX;
		entity.anchorOffsetY = anchorY;
		entity.x += (anchorX - oldAnchorX);
		entity.y += (anchorY - oldAnchorY);
	}

	/**
	 * @description 角度转弧度
	 * @author (pdh)
	 * @date 2020-11-09
	 * @param {number} angle
	 * @returns {number}
	 * @memberof ShowUtil
	 */
	public angle2radian(angle: number): number {
		return angle * Math.PI / 180;
	}


	/**
	 * @description 弧度转角度
	 * @author (pdh)
	 * @date 2020-11-09
	 * @param {number} radian
	 * @returns {number}
	 * @memberof ShowUtil
	 */
	public radian2angle(radian: number): number {
		let angle = radian * 180 / Math.PI; //弧度转角度,方便调试
		return angle;
	}

    /**
     * @description 将坐标控制在0~360度之间
     * @author (pdh)
     * @date 2020-11-09
     * @private
     * @param {number} angle
     * @returns {number}
     * @memberof ShowUtil
     */
	public getRealAngle(angle: number): number {
		let shang = parseInt(String(angle / 360));
		angle = angle - shang * 360;

		if (angle > 360) {
			angle -= 360;
		} else if (angle < 0) {
			angle += 360;
		}
		return angle;
	}

	/**
	 * @description 两条线段是否相交。如果有相交点放在{@resultPoint}中返回。
	 *              只有return为true时,{@resultPoint}才有意义。
	 * @author (pdh)
	 * @date 2020-11-08
	 * @param {egret.Point} line1Start 线段1的起点
	 * @param {egret.Point} line1End 线段1的终点
	 * @param {egret.Point} line2Start 线段2的起点
	 * @param {egret.Point} line2End 线段2的终点
	 * @param {egret.Point} resultPoint  相交点
	 * @returns {boolean}  是否相交
	 * @memberof ShowUtil
	 */
	public crashLine(line1Start: egret.Point,
		line1End: egret.Point,
		line2Start: egret.Point,
		line2End: egret.Point,
		resultPoint: egret.Point): boolean {

		let pt = resultPoint;
		// line1's cpmponent  
		let x1 = line1End.x - line1Start.x;//b1  
		let y1 = line1End.y - line1Start.y;//a1  
		// line2's cpmponent  
		let x2 = line2End.x - line2Start.x;//b2  
		let y2 = line2End.y - line2Start.y;//a2  
		// distance of 1,2  
		let x21 = line2Start.x - line1Start.x;
		let y21 = line2Start.y - line1Start.y;
		// determinant  
		let D = y1 * x2 - y2 * x1;// a1b2-a2b1  
		//   
		if (0 != D) {
			// cross point  
			pt.x = (x1 * x2 * y21 + y1 * x2 * line1Start.x - y2 * x1 * line2Start.x) / D;
			// on screen y is down increased !   
			pt.y = -(y1 * y2 * x21 + x1 * y2 * line1Start.y - x2 * y1 * line2Start.y) / D;
			// segments intersect.  
			if ((Math.abs(pt.x - line1Start.x - x1 / 2) <= Math.abs(x1 / 2)) &&
				(Math.abs(pt.y - line1Start.y - y1 / 2) <= Math.abs(y1 / 2)) &&
				(Math.abs(pt.x - line2Start.x - x2 / 2) <= Math.abs(x2 / 2)) &&
				(Math.abs(pt.y - line2Start.y - y2 / 2) <= Math.abs(y2 / 2))) {
				return true;
			}
		}
		return false;
	}


    /**
     * @description 计算夹角,沿X轴正向为0,逆时针增大
     * @author (pdh)
     * @date 2020-11-06
     * @param {number} fromX
     * @param {number} fromY
     * @param {number} toX
     * @param {number} toY
     * @returns 
     * @memberof ShowUtil
     */
	public getAngle(fromX: number, fromY: number, toX: number, toY: number) {
		let x = toX - fromX;
		let y = toY - fromY;//egret中左上角为原点,要做一下转换
		let radian = Math.atan2(y, x);
		let angle = this.radian2angle(radian); //弧度转角度,方便调试
		angle = this.getRealAngle(angle);
		return angle;
	}



	/**
	 * @description 以baseX、baseY为原点,旋转rotateAngle的角度,获得beforeX、beforeY旋转后的新坐标
	 * @author (pdh)
	 * @date 2020-12-20
	 * @param {number} baseX
	 * @param {number} baseY
	 * @param {number} beforeX
	 * @param {number} beforeY
	 * @param {number} rotateAngle
	 * @param {egret.Point} resultPos
	 * @returns {egret.Point}
	 * @memberof ShowUtil
	 */
	public rotateByBasePoint(baseX: number, baseY: number,
		beforeX: number, beforeY: number,
		rotateAngle: number,
		resultPos: egret.Point): egret.Point {
		let baseP: egret.Point = ObjectPool.pop(ObjectType.Point);
		baseP.setTo(baseX, baseY);

		let beforeP: egret.Point = ObjectPool.pop(ObjectType.Point);
		beforeP.setTo(beforeX, beforeY);

		let distance = egret.Point.distance(beforeP, baseP);
		let beforeAngle = this.getAngle(baseX, baseY, beforeX, beforeY);
		let afterAngle = this.getRealAngle(beforeAngle + rotateAngle);

		let radian = this.angle2radian(afterAngle);
		resultPos.x = Math.cos(radian) * distance + baseX;
		resultPos.y = Math.sin(radian) * distance + baseY;

		ObjectPool.push(baseP);
		ObjectPool.push(beforeP);
		return resultPos;
	}

    /**
     * @description 炮弹射程1500就够了
     * @author (pdh)
     * @date 2020-11-08
     * @static
     * @returns {number}
     * @memberof ShowUtil
     */
	public getMaxDistance(): number {
		let w = GDatas.getStageWidth();
		let h = GDatas.getStageHeight();
		let distance = Math.sqrt(w * w + h * h);
		return distance + 100;
	}

	/**
	 * @description 判断点是否落在矩形内。 注意注意:矩形顶角坐标传入次序不要搞错
	 * @author (pdh)
	 * @date 2020-12-20
	 * @param {egret.Point} checkPoint  要检测的点
	 * @param {egret.Point} rectLT		左上角
	 * @param {egret.Point} rectRT		右上角
	 * @param {egret.Point} rectRB		右下角
	 * @param {egret.Point} rectLB		左下角
	 * @returns {boolean}
	 * @memberof ShowUtil
	 */
	public isPointInRect(checkPoint: egret.Point, rectLT: egret.Point, rectRT: egret.Point, rectRB: egret.Point, rectLB: egret.Point): boolean {
		let isIn = false;
		let dot: egret.Point = ObjectPool.pop(ObjectType.Point);
		dot.setTo(checkPoint.x, checkPoint.y);
		let lt: egret.Point = ObjectPool.pop(ObjectType.Point);
		lt.setTo(rectLT.x, rectLT.y);
		let rt: egret.Point = ObjectPool.pop(ObjectType.Point);
		rt.setTo(rectRT.x, rectRT.y);
		let rb: egret.Point = ObjectPool.pop(ObjectType.Point);
		rb.setTo(rectRB.x, rectRB.y);
		let lb: egret.Point = ObjectPool.pop(ObjectType.Point);
		lb.setTo(rectLB.x, rectLB.y);
		let angle = this.getAngle(lt.x, lt.y, rt.x, rt.y);

		//以左上角lt为原点,将要判断的各个点转换为正常坐标系
		this.rotateByBasePoint(lt.x, lt.y, rt.x, rt.y, -angle, rt);
		this.rotateByBasePoint(lt.x, lt.y, rb.x, rb.y, -angle, rb);
		this.rotateByBasePoint(lt.x, lt.y, lb.x, lb.y, -angle, lb);
		this.rotateByBasePoint(lt.x, lt.y, dot.x, dot.y, -angle, dot);

		let x = lt.x < rb.x ? lt.x : rb.x;
		let y = lt.y < rb.y ? lt.y : rb.y;
		let width = Math.abs(rb.x - lt.x);
		let height = Math.abs(rb.y - lt.y);
		if ((dot.x >= x && dot.x < (x + width))
			&& (dot.y >= y && dot.y < (y + height))) {
			isIn = true;
		}

		ObjectPool.push(lt);
		ObjectPool.push(rt);
		ObjectPool.push(rb);
		ObjectPool.push(lb);
		ObjectPool.push(dot);
		return isIn;
	}
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值